sequenceA 如何处理成对列表?

Enr*_*lis 6 haskell applicative

抛开这个问题。直觉上,我已经理解了sequenceA该用例中的作用,但不知道它是如何/为什么这样工作的。

所以这一切都归结为这个问题:sequenceA在以下情况下如何工作?

> sequenceA [("a",1),("b",2),("c",3)]
("abc",[1,2,3])
Run Code Online (Sandbox Code Playgroud)

我看到

sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
Run Code Online (Sandbox Code Playgroud)

所以在上面的用例中Traversableis[]Applicative,因为(,)是一个二进制类型构造函数, is (,) a,这意味着这对被视为其snd字段上的应用函子。这与最终在snd结果中的列表结合在一起。所以我们从一个对的列表到第二个字段中有一个列表的对。

但是"abc"从哪里来?我的意思是,我知道这fst是所有对的串联,但我不知道它是通过++还是通过sconcat的列表fstsequenceA的签名中似乎没有任何内容可以强制使对中的fsts 可以组合在一起。

仍然必须在某处使用该假设。确实,以下失败

sequenceA [('a',1),('b',2),('c',3)]
Run Code Online (Sandbox Code Playgroud)

Dan*_*ner 7

它使用mappend. Applicative它使用的实例如下所示:

instance Monoid a => Applicative ((,) a) where
    pure x = (mempty, x)
    (af, f) <*> (ax, x) = (mappend af ax, f x)
Run Code Online (Sandbox Code Playgroud)


dan*_*iaz 5

在 Haskell 中,一个类型的类型类实例可以“有条件”地存在于该类型的某些部分的其他类型类实例中。并非该表单的所有类型构造函数((,) a)都是 的实例Applicative,而只有a类型具有Monoid实例的那些。

这些必需的约束出现在=>实例的 Haddocks 之前,如下所示:

Monoid a => Applicative ((,) a)
Run Code Online (Sandbox Code Playgroud)

为什么Monoid需要实例?首先,purefor((,) a)需要a凭空实现一个值以放入元组的第一个元素。mempty因为类型a可以完成工作。


可以有几层深的所需约束链。例如,为什么下面的工作?

ghci> import Datta.Function ((&)) -- flipped application
ghci> [(id :: String -> String, 2 :: Int), (\x -> x ++ x, 1)] & sequenceA & fst $ "foo"
"foofoofoo"
Run Code Online (Sandbox Code Playgroud)

这里的第一个组件是一个函数。和以前一样,它必须有一个Monoid实例sequenceA才能工作。但是什么时候是a -> ba类型Monoid呢?查看黑线鳕,我们发现:

Monoid b => Monoid (a -> b)
Run Code Online (Sandbox Code Playgroud)

也就是说,Monoid当返回类型(此处String)为 a时,函数为s Monoid

实际上,还有另一个 Monoid可以通过Endonewtype使用的函数实例。使用 newtypes 来选择用于给定操作的实例是很常见的,尽管它需要一些包装和解包。