我的问题与另一个问题的答案有关:https://dev59.com/hWbWa4cB1Zd3GeqPas0U#11766789
在他的答案中,ertes写下了以下类型签名。
请帮我解释一下元组
谢谢, Max
---编辑:---
@Lee 提醒新手在尝试理解类型之前要进行 desugar。展开语法糖后,问题函数看起来像这样:
select :: [a] -> [(a, [a])]
然而,当实际使用select
时,ertes会在do
块中写入以下内容。
(y, ys) <- select xs
请帮我解释一下元组
(y, ys)
如何匹配 select 函数的返回类型,即 [(a, [a])]
。Haskell 是否在某个时候对类型进行了强制转换?(Haskell 是否曾经进行过类型强制转换?)<-
是从 select
返回的列表单子中提取类型为 (a, [a])
的元组吗?谢谢, Max
---编辑:---
@Lee 提醒新手在尝试理解类型之前要进行 desugar。展开语法糖后,问题函数看起来像这样:
select xs >>= \(y, ys) -> fmap (y:) (perms (n - 1) ys)
对于列表,xs >>= f = concat (map f xs)
。因此,在这个上下文中更好地解读 (y, ys)
是将要映射到列表上的函数的签名。
select
返回一个列表。如果你写a <- select xs
,那么a
就是select xs
的每个元素。如果之后你写了func a
,那么这个的结果就是将func
应用于select xs
中的每个元素得到的结果。这就是列表单子的定义方式。a <- select xs; func a
和select xs >>= func
是一样的。对于列表绑定操作的定义为:m >>= f = concat (map f m)
,所以你可以写成map func (select xs)
。在 Haskell 中没有类型强制转换。 - user2407038a
不是指代 '每个元素',而是表示列表中的一个(任意但具体的)元素。 - Justin L.