haskell – 我可以通过应用函子的组合来建模具有短路故障成功的列表吗?

用户’singpolyma’ asked on reddit如果有一些基本的一般结构:

data FailList a e = Done | Next a (FailList a e) | Fail e

建议一个免费的monad,但是我想知道是否可以通过应用程序函子更一般地建模.在Abstracting with Applicatives年,巴兹曼向我们展示了两个应用函数的总和也是一个应用函数,偏向左/右,只要我们在偏向的方向上有一个自然的转变.这听起来像是我们需要的!因此,我开始了我的建议,但很快遇到了问题.任何人都可以看到解决这些问题的方法吗?

首先,我们从两个函子的总和开始.我从这里开始,因为我们想模拟总和类型 – 无论是成功还是成功,都是失败的.

data Sum f g a = InL (f a) | InR (g a)

和我们想要合作的两个函子是:

data Success a = Success [a]
data Failure e a = Failure e [a]

成功是直接的 – 它本质上是Const [a].然而,失败e我不太清楚.这不是一个应用函子,因为纯粹没有任何定义.然而,这是Apply的一个例子:

instance Functor Success where
  fmap f (Success a) = Success a

instance Functor (Failure e) where
  fmap f (Failure e a) = Failure e a

instance Apply (Failure e) where
  (Failure e a) <.> (Failure _ b) = Failure e a

instance Apply Success where
  (Success a) <.> (Success b) = Success (a <> b)

instance Applicative Success where
  pure = const (Success [])
  a <*> b = a <.> b

接下来,我们可以定义这些函子的总和,从右到左进行自然变换(因此是左偏差):

instance (Apply f, Apply g, Applicative g, Natural g f) => Applicative (Sum f g) where
  pure x = InR $pure x
  (InL f) <*> (InL x) = InL (f <*> x)
  (InR g) <*> (InR y) = InR (g <*> y)
  (InL f) <*> (InR x) = InL (f <.> eta x)
  (InR g) <*> (InL x) = InL (eta g <.> x)

我们现在唯一要做的就是定义我们的自然转型,这就是它所有的崩溃.

instance Natural Success (Failure e) where
  eta (Success a) = Failure ???? a

无法创建失败似乎是问题.此外,即使是hacky,也不使用⊥不是一个选项,因为这将被评估,在你有InR(Success …)< *> InL(失败…).

我觉得我错过了一些东西,但我不知道是什么.

这可以做吗

我非常确定“正确”的答案是使一个单一的,就像你不喜欢讨论的想法一样.

考虑失败“oops”[(* 1),(* 2),(* 3)] *失败“doh”[1,2,3]结果应该是“oops”还是“doh”?通过使e成为一个单一的,我们捕捉到没有规范选择的事实,并让消费者选择他们的毒药(无论是第一,最后,[]等)

请注意,这个解决方案,非常像(Maybe e,[a])表示,不能正确处理流/潜在的无限数据,因为我们是否有一个失败结束列表是严格的.

根据后续文章(http://comonad.com/reader/2013/algebras-of-applicatives/),不同的编码将使用固定点.

然后,您将列出的列表表示(FixF(ProductF Embed(Sum(Const())))a),并通过将错误单调放在单元位置来进行更改,以获得以下内容:

Monid mon => FixF(ProductF Embed(Sum(Const mon)))a

并且请注意,您可以使用Maybe而不是一个完整的FailList来完成,但是与FailList一样,您不会免费获得应用程序实例,除非您编写一个指定组合错误的正确方法.

还要注意,如果我们具有相当于Success [(* 1),(* 2),(* 3)] *失败的“doh”[1,2,3,4,5]然后我们用三个要素(即我们真的是无限制的)恢复了一个成功,而在你提出的方法中,我们通过三个元素和五元素失败列表中的错误.这是流量与严格的权衡.

最后,最直接的,我们可以使用类型FailList e = Product(Const(First e))ZipList来使用标准应用机器,并获得与原始数据类型非常接近的东西.

相关文章
相关标签/搜索