haskell - applicative 到底有多重要,而不是 "combining"?

标签 haskell type-constraints applicative category-theory

对于 uncertainty-propagating Approximate type , 我想要 Functor 的实例通过Monad .然而这不起作用,因为我需要包含类型的向量空间结构,所以它实际上必须是类的受限版本。因为似乎仍然没有针对那些的标准库(或者是否存在?请指出我。有 rmonad ,但它使用 * 而不是 Constraint 作为上下文类型,这对我来说似乎已经过时了),我写了my own version暂且。

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 ($)

而不是一种方法。没有约束,这是完全等价的(实际上是 many Applicative instances go this way anyway ),但在这种情况下它实际上更好:(<*>#)仍然对 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 original blog post on constraint kinds 中已经给出的示例.

所以我的问题:

<*>liftA2 更基本?

同样,在不受约束的情况下,它们无论如何都是等价的。我居然找到了liftA2更容易理解,但在 Haskell 中,考虑传递“函数容器”而不是对象容器和一些“全局”操作来组合它们可能更自然。和<*>直接引出所有liftAμ对于 μ ∊ ℕ,不仅仅是 liftA2 ;从 liftA2 开始仅限 doesn't really work .

但是,这些受约束的类似乎对 liftA2 很重要。 .特别是,它允许 CApplicative所有 CMonad 的实例s,当 <*># 时不起作用是基础方法。我想我们都同意Applicative应该总是比 Monad 更通用.

范畴论者会对这一切说什么?有没有办法获取通用liftAμ没有 a->b需要满足相关的约束?

*该类型的线性函数实际上确实具有向量空间结构,但我绝对不能将自己局限于这些。

最佳答案

据我了解(作为非范畴理论家),基本操作是zip :: f a -> f b -> f (a, b) (将一对有效计算映射到产生一对的有效计算)。

然后你可以定义

  • fx <*> fy = uncurry ($) <$> zip fx fy
  • liftA2 g fx fy = uncurry g <$> zip fx fy

  • 看到这个post by Edward Yang , 我找到了 via the Typeclassopedia .

    关于haskell - applicative 到底有多重要,而不是 "combining"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13625905/

    相关文章:

    c# - 如何获取旧式集合中项目的类型?

    haskell - 将 MonadReader/MonadError 实例添加到 Transformer 类型

    haskell - 为什么 Haskell 没有在函数签名中推断数据类型的类型类?

    c# - 一个特殊的 "convertability from int"可以作为 C# 中的类型约束吗?

    haskell - <*> 如何与 Function Applicative 一起使用?

    haskell - (r ->) 应用仿函数

    haskell - 为索引单子(monad)重新绑定(bind) do 表示法

    haskell - "undoable"应用仿函数的例子?

    haskell - Cabal 安装包奇怪地失败

    parsing - Haskell 中的级联解析器