正如标题所说,我并没有完全理解哈斯克尔如何解释
1:[[]]
为什么它似乎do(1:[]):[]
?
E:我得到了这个想法:
part'::[a] -> [[a]]
part' [] = [[]]
part' (x:xs) = p ++ [x:ys | ys <- p]
where p = part' xs
特别是来自p ++ [x:ys | ys <- p]
例如。对于part'[1]
:我的思路是否正确?:
part'[1] = (part'[]) ++ [1:ys | ys <- part'[]]
--> = [[]] ++ [1:[[]]]
希望这说清楚。
好像你误解了[... | ys <- p]
的语法。在这种情况下,ys
是列表p
的每个元素的替身,而不是整个列表。你问题的最后部分的等式推理应该是
part' [1] = (part' []) ++ [1:ys | ys <- p]
-- = [[]] ++ [1:ys | ys <- [[]]]
-- = [[]] ++ [1 : []]
-- = [[], [1]]
Haskell中的[]
可能非常令人困惑。
空括号[]
本身就是空列表的构造函数。通常这可以通过这个替代(同构)列表定义来解释,其中[]
被称为Nil
而:
被称为Cons
。
data List a
= Nil
| Cons a (List a)
当您考虑到任何有限列表最终都有Nil
时,事情并不会变得更容易。这是结束递归的唯一可行方法,例如:
Cons 3 (Cons 4 (Cons 5 Nil))
或者,等效地:
3 : (4 : (5 : []))
一些混淆来自这个方便的语法,它再次表达相同:
[3, 4, 5]
现在有人可能只是将[]
读作empty list
而没有任何关于Cons
和Nil
的线索。
然而还有更多:在类型签名中,你遇到像[Int]
或[a]
这样的东西,这意味着List Int
或List a
,因此括号 - 再次 - 表达一个完全不同的东西。
关于Haskell中括号的含义存在虚假直觉的风险,突然之间你必须认真思考像[1]
和[[1]]
,或1:[]
和(1:[]):[]
这样的事物的确切含义。
看,列表:
[a,b,c] ++ [d,e,f] =
[a,b] ++ [c,d,e,f] =
[a] ++ [b,c,d,e,f] =
[] ++ [a,b,c,d,e,f] =
a : [b,c,d,e,f] =
a : b : [c,d,e,f] =
a : b : c : [d,e,f] =
a : b : c : d : [e,f] =
a : b : c : d : e : [f] =
a : b : c : d : e : f : [] =
[a,b,c,d,e,f] ++ [] =
[a,b,c,d,e] ++ [f] =
[a,b,c,d] ++ [e,f] =
[a,b,c] ++ [d,e,f]
和列表理解:
[[a, 0] | a <- [1,2,3]] =
[r | a <- [1,2,3], r <- [[a, 0]]] =
concatMap (\a -> [[a, 0]]) [1,2,3] =
[[1, 0]] ++ [[2, 0]] ++ [[3, 0]] =
[[1, 0], [2, 0], [3, 0]]