我正在尝试编写一个函数,从Haskell中的列表返回所有排列:
perms :: [a] -> [[a]]
perms [] = [[]]
perms xs = map (\y -> concat_each y (perms (list_without y xs))) xs
list_without :: (Eq a) => a -> [a] -> [a]
list_without x xs =
filter (\y -> not (y==x)) xs
concat_each :: a -> [[a]] -> [[a]]
concat_each x xs =
map (\y -> x:y) xs
我认为第三行会发生什么:
y是a
,x是[a]
,所以
list_without y xs是[a]
。
权限(list_without ...)因此为[[a]]
因此concat_each y(权限...)得到a
和[[a]]
,从而得到[[a]]
地图的功能是a -> [[a]]
,一切都应该没事。
但是编译器似乎有不同的看法:
Couldn't match type `a' with `[a]'
`a' is a rigid type variable bound by
the type signature for perms :: [a] -> [[a]]
at C:\Users\Philipp\Desktop\permutations.hs:1:10
Expected type: [a]
Actual type: [[a]]
Relevant bindings include
y :: a (bound at permutations.hs:3:18)
xs :: [a] (bound at permutations.hs:3:7)
perms :: [a] -> [[a]]
(bound at permutations.hs:2:1)
In the expression: concat_each y (perms (list_without y xs))
In the first argument of `map', namely
`(\ y -> concat_each y (perms (list_without y xs)))'
如何正确调试此错误消息?我真的不知道从哪里开始检查我的类型。
答案 0 :(得分:5)
map :: (x -> y) -> [x] -> [y]
您提供给map
的第一个参数的类型为a -> [[a]]
,即x = a
和y = [[a]]
,
:: [x] -> [ y ]
map (\y -> ...) :: [a] -> [[[a]]]
-- ^ ^^^^^
-- x = a, y = [[a]]
在这种情况下,该map (\y -> ...) xs
的结果是一个列表,其中每个元素对应于从y
中的固定元素xs
开始的排列。最后,您不必关心置换从哪个元素开始;您可以忘记使用concat
进行分隔:
perms = concat (map (\y -> ...) xs)
-- or
perms = concatMap (\y -> ...) xs
-- or
perms = xs >>= \y -> ...