lef*_*out 12 haskell type-constraints category-theory applicative
对于不确定性传播Approximate类型,我想要Functor通过实例Monad.然而,这不起作用,因为我需要在包含的类型上使用向量空间结构,因此它实际上必须是类的受限版本.由于仍有似乎并不为那些标准库(或者是那里?请点我.还有rmonad,但它使用*,而不是Constraint作为上下文样,这似乎只是过时的我),我写我自己的版本的暂时的.
这一切都很容易 Functor
class CFunctor f where
type CFunctorCtxt f a :: Constraint
cfmap :: (CFunctorCtxt f a, CFunctorCtxt f b) => (a -> b) -> f a -> f b
instance CFunctor Approximate where
type CFunctorCtxt Approximate a = FScalarBasisSpace a
f `cfmap` Approximate v us = Approximate v' us'
where v' = f v
us' = ...
Run Code Online (Sandbox Code Playgroud)
但是直接翻译Applicative,就像
class CFunctor f => CApplicative' f where
type CApplicative'Ctxt f a :: Constraint
cpure' :: (CApplicative'Ctxt f a) => a -> f a
(#<*>#) :: ( CApplicative'Ctxt f a
, CApplicative'Ctxt f (a->b)
, CApplicative'Ctxt f b) => f(a->b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
因为函数a->b没有必要的向量空间结构*是不可能的FScalarBasisSpace.
然而,有效的是改变受限制的应用类的定义:
class CFunctor f => CApplicative f where
type CApplicativeCtxt f a :: Constraint
cpure :: CAppFunctorCtxt f a => a -> f a
cliftA2 :: ( CAppFunctorCtxt f a
, CAppFunctorCtxt f b
, CAppFunctorCtxt f c ) => (a->b->c) -> f a -> f b -> f c
Run Code Online (Sandbox Code Playgroud)
然后定义<*>#而不是cliftA2作为自由函数
(<*>#) = cliftA2 ($)
Run Code Online (Sandbox Code Playgroud)
而不是方法.如果没有约束,这是完全等效的(事实上,很多Applicative情况下,走这条路呢),但在这种情况下,它实际上是更好的:(<*>#)仍然有约束a->b其Approximate不能履行,但不伤可适用的情况下,我仍然可以做有用的东西,如
ghci> cliftA2 (\x y -> (x+y)/x^2) (3±0.2) (5±0.3) :: Approximate Double
0.8888888888888888 +/- 0.10301238090045711
Run Code Online (Sandbox Code Playgroud)
我认为情况对于许多其他用途基本相同,例如已经在约束种类的原始博客文章中给出CApplicative的Set示例.
是<*>不是更根本的liftA2?
同样,在无约束的情况下,无论如何它们都是等价的.实际上我发现它liftA2更容易理解,但在Haskell中,考虑传递"函数容器"而不是对象容器和一些"全局"操作来组合它们可能更自然.并<*>直接导致所有liftA?的μ εℕ,不仅仅是liftA2; 这样做liftA2只是不起作用.
但是,这些受限制的类似乎非常重要liftA2.特别地,它允许CApplicative对所有实例CMonads,这也不能在工作时<*>#是基本方法.而且我认为我们都同意Applicative应该总是比一般Monad.
类别理论家对所有这些都说了什么?有没有办法获得一般liftA?而不a->b需要满足相关的约束?
*该类型的线性函数实际上具有向量空间结构,但我绝对不能将自己局限于那些.
dav*_*420 11
据我所知(作为一个非类别的理论家),基本操作是zip :: f a -> f b -> f (a, b)(将一对有效的计算映射到一个有效的计算导致一对).
然后你可以定义
fx <*> fy = uncurry ($) <$> zip fx fyliftA2 g fx fy = uncurry g <$> zip fx fy请参阅Edward Yang发表的这篇文章,我通过Typeclassopedia找到了这篇文章.
| 归档时间: |
|
| 查看次数: |
624 次 |
| 最近记录: |