Haskell 关于哈斯克尔的问题';s序列函数
我一直在读UPenn的CS194,目前正在听第七讲Monads。我一直以为自己对单子的掌握还不错,直到我看到了sequence函数的实现并开始四处探索Haskell 关于哈斯克尔的问题';s序列函数,haskell,monads,Haskell,Monads,我一直在读UPenn的CS194,目前正在听第七讲Monads。我一直以为自己对单子的掌握还不错,直到我看到了sequence函数的实现并开始四处探索 sequence :: Monad m => [m a] -> m [a] sequence [] = return [] sequence (ma:mas) = do a <- ma as <- sequence mas return (a:as) 我认为x,或者a在sequence的情况下应该是Num。
sequence :: Monad m => [m a] -> m [a]
sequence [] = return []
sequence (ma:mas) = do
a <- ma
as <- sequence mas
return (a:as)
我认为x
,或者a
在sequence
的情况下应该是Num
。但它一定是Num
的Monad
。当Just x
从的实例定义中被拉出x
时,x
如何成为Num
的单子
return[]
的类型是Monad m=>m[t]
——这里,[]
是[t]
的一个实例,即一个任意类型的列表(该类型是任意的,因为它是空列表,所以无论如何都没有该类型的实例)。如果替换列表单子,return
的类型是t->[t]
,而return[]
产生[[]]
。令人困惑的是,monad和包含的值都是列表
return
的类型通常是Monad m=>t->mt
。如果专门处理列表,则会得到t->[t]
,因此列表类型将取代m
。列表的特殊语法使其更加混乱;如果改用maybe monad,则专用返回的类型为t->maybe t
,因此您可以清楚地看到m
是如何被maybe
替换的。在maybe monad中,return[]
的类型是maybe[t]
:monad现在包装了一些列表
return[]
的类型是Monad m=>m[t]
,一个由Monad包装的列表。如果使用列表monad,则用列表构造函数替换m
,并得到正确的类型[[t]]
至于第二个问题,你为什么认为a
必须是单子
在评论中澄清后编辑
在您给出的示例调用序列[Just 5,Just 9]
中,monad可能是,而不是list;该列表是序列类型所需的普通列表。请记住,它需要一个[ma]
作为输入。当您提供一个numa=>[maybea]
作为输入时,这使得monadmaybea
,结果类型是numa=>maybea[a]
<代码>顺序
将可选值列表转换为可选列表。这意味着在序列
的第一种情况下,返回[]
适用于可能
的返回
,并且表示仅[]
。这是有意义的,因为在单子中调用sequence[]
应该返回Just[]
现在,在第二种情况的do块中,我们有一组变量,这有助于确定每个变量的类型。对于具体的Maybe
和Int
数字,我会这样做;在所有这些情况下,获取泛型类型归结为简单地用m
替换Maybe
,用a
替换Int
,并添加约束
整个输入的类型为[Maybe Int]
。第二个案例模式与(ma:mas)
匹配,从列表中选择第一个元素。因此,ma
具有列表元素的类型,Maybe Int
,而ma
是列表的其余部分,因此具有类型[Maybe Int]
在do块中,ma
用箭头符号展开,结果是a
,因此其类型为ma
,单子被剥离,即Int
然后,递归调用序列
,其余输入为mas
,其类型为[Maybe Int]
。替换为序列的类型
表明结果类型是可能是[Int]
。此值再次展开,因此目标as
具有类型[Int]
在最后一行中,a
(typeInt
)作为
(type[Int]
)的前缀,产生一个较长的列表([Int]
)。结果被赋予return
,它将其包装在一个Just
(可能[Int]
)中,以匹配序列的结果类型
顺便说一句,如果您想通过do块详细跟踪类型,您应该首先使用lambdas将它们分解为正常组合。这里的return[]
不是\x->[x]
的monad实例中的[]
-它是m
monad中的return
函数(因此结果将取决于m
实际上是什么)-想想m=Maybe
如果它对你有帮助-因此return[]
将是Just[]
2。)如果你调用sequence[Just 5,Just 9]
,那么a的类型将是someNum
是(a
将是5
和9
)-而没有“Monad”在Num
/5
-你可以说它在s中只是`;)谢谢。这让事情更清楚了。事实上,列表Monad的m[t]
是[[t]]
在你指出它之前,我一直在逃避。我认为这有助于我对a
类型的第二次混淆。我认为它必须是一个单子包装的值,因为我不知道Num如何与m[t]
相结合,但是如果return[]
本质上是[[[]]
,那么如何结合呢(Num:[[]])
work?扩展了答案,希望能消除您的困惑。
Just x >>= k = k x