Haskell 关于哈斯克尔的问题';s序列函数

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。

我一直在读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
。但它一定是
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]
作为输入时,这使得monad
maybea
,结果类型是
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
(type
Int
)作为
(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的类型将是some
Num
是(
a
将是
5
9
)-而没有“Monad”在
Num
/
5
-你可以说它在
s中只是`;)谢谢。这让事情更清楚了。事实上,列表Monad的
m[t]
[[t]]
在你指出它之前,我一直在逃避。我认为这有助于我对
a
类型的第二次混淆。我认为它必须是一个单子包装的值,因为我不知道Num如何与
m[t]
相结合,但是如果
return[]
本质上是
[[[]]
,那么
如何结合呢(Num:[[]])
work?扩展了答案,希望能消除您的困惑。
Just x  >>= k = k x