对于不确定性传播Approximate
类型,我希望有Functor
through的实例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' = ...
但直接翻译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
不可能,因为函数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
然后定义<*>#
而不是cliftA2
作为自由函数
(<*>#) = cliftA2 ($)
而不是一种方法。没有约束,这是完全等价的(事实上,很多Applicative
实例都是这样),但在这种情况下,它实际上更好:(<*>#)
仍然有无法满足的约束a->b
,Approximate
但这不会伤害应用实例,而且我仍然可以做有用的事情,比如
ghci> cliftA2 (\x y -> (x+y)/x^2) (3±0.2) (5±0.3) :: Approximate Double
0.8888888888888888 +/- 0.10301238090045711
我认为CApplicative
对于. Set
_
所以我的问题:
比? <*>
_liftA2
同样,在不受约束的情况下,它们无论如何都是等价的。我实际上发现liftA2
更容易理解,但在 Haskell 中,考虑传递“函数容器”而不是对象容器和一些“全局”操作来组合它们可能更自然。并<*>
直接引出所有liftAμ
对于μ ∊ ℕ,而不仅仅是liftA2
; 从liftA2
only这样做是行不通的。
但是,这些受约束的类似乎对liftA2
. 特别是,它允许所有s 的CApplicative
实例,这在基方法时不起作用。而且我认为我们都同意应该始终比.CMonad
<*>#
Applicative
Monad
范畴论者会对这一切说什么?有没有办法在liftAμ
不需要a->b
满足相关约束的情况下获得将军?
*这种类型的线性函数实际上确实具有向量空间结构,但我绝对不能局限于这些。