haskell - 如何构造带约束的 Applicative 实例(类似于使用 ContT 构造 Monad 实例)

标签 haskell applicative type-constraints category-abstractions

This question处理构建一个适当的Monad来自单子(monad)的实例,但仅在某些约束下 - 例如Set .诀窍是将其包装成 ContT ,它将约束推迟到包装/展开其值。

现在我想对 Applicative 做同样的事情s。特别是,我有一个 Applicative pure 具有类型类约束的实例。有没有类似的技巧来构造一个有效的 Applicative实例?

(是否有像 there is for monads 一样的“所有应用仿函数之母”?)

最佳答案

Category 开始可能是最一致的可用方式。 ,对对象有限制是很自然的:对象!

class Category k where
  type Object k :: * -> Constraint
  id :: Object k a => k a a
  (.) :: (Object k a, Object k b, Object k c)
     => k b c -> k a b -> k a c

然后我们定义类似于 how Edward does it 的仿函数
class (Category r, Category t) => Functor f r t | f r -> t, f t -> r where
  fmap :: (Object r a, Object t (f a), Object r b, Object t (f b))
             => r a b -> t (f a) (f b)

所有这些工作都很好,并在 constrained-categories library 中实现。 ,哪——真丢人! – 仍然不在 Hackage 上。
Applicative不幸的是,做起来不那么简单。 Mathematically, these are monoidal functors , 所以 we first need单曲面类别。 categories has that class ,但它不适用于基于约束的版本,因为我们的对象总是任何类型的 *有一个约束。所以我做的是编一个 Curry class , 哪种近似。

然后,我们可以做 Monoidal functors :
class (Functor f r t, Curry r, Curry t) => Monoidal f r t where
  pure :: (Object r a, Object t (f a)) => a `t` f a
  fzipWith :: (PairObject r a b, Object r c, PairObject t (f a) (f b), Object t (f c))
              => r (a, b) c -> t (f a, f b) (f c)

这实际上等价于 Applicative当我们有适当的封闭笛卡尔类别时。在受限类别版本中,不幸的是,签名看起来非常糟糕:
  (<*>) :: ( Applicative f r t
           , MorphObject r a b, Object r (r a b)
           , MorphObject t (f a) (f b), Object t (t (f a) (f b)), Object t (f (r a b))
           , PairObject r (r a b) a, PairObject t (f (r a b)) (f a)
           , Object r a, Object r b, Object t (f a), Object t (f b))
       => f (r a b) `t` t (f a) (f b)

尽管如此,它确实有效——对于不受约束的情况,呵呵!我还没有找到一种方便的方法来使用它与非平凡的约束。

但是,Applicative相当于Monoidal ,并且可以按照 the Set example 中的演示使用.

关于haskell - 如何构造带约束的 Applicative 实例(类似于使用 ContT 构造 Monad 实例),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21099466/

相关文章:

F# 缺少类型约束

haskell - 如果值构造函数也应该是类型怎么办?

haskell - 使用 Data.Acid 时如何处理更改事件的实现

linux - 在读取带有惰性字节串的大文件时减少内核开销

haskell - <*> 如何从 pure and (>>=) 派生出来?

Haskell:一些和很多

TypeScript 无法在函数类型中派生类型约束

haskell - 递归更新 Sodium 中的 "Behaviour"产生 'thread blocked ...'

haskell - 应用重写 (Haskell)

c# - 重载选择和类型约束特性