Debugging Haskell置换函数不编译
我正在复习一些Haskell,我正在尝试编写一个置换函数,它将映射[1,2,3]>[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]。我有以下几点-Debugging Haskell置换函数不编译,debugging,haskell,types,compiler-errors,permutation,Debugging,Haskell,Types,Compiler Errors,Permutation,我正在复习一些Haskell,我正在尝试编写一个置换函数,它将映射[1,2,3]>[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]。我有以下几点- permute:: [a] -> [[a]] permute [] = [] permute list = map f list where f x = listProduct x (permute (exclude x list))
permute:: [a] -> [[a]]
permute [] = []
permute list = map f list
where
f x = listProduct x (permute (exclude x list))
exclude e list1 = filter (/= e) list1
listProduct x list2 = map (x :) list2
下面是我收到的错误消息-
permutations.hs:3:20:
Couldn't match type `a' with `[a]'
`a' is a rigid type variable bound by
the type signature for permute :: [a] -> [[a]]
at permutations.hs:1:11
Expected type: a -> [a]
Actual type: a -> [[a]]
In the first argument of `map', namely `f'
In the expression: map f list
In an equation for `permute':
permute list
= map f list
where
f x = listProduct x (permute (exclude x list))
exclude e list1 = filter (/= e) list1
listProduct x list2 = map (x :) list2
Failed, modules loaded: none.
我会尝试调试,但它甚至无法编译。有什么想法吗?让我们只关注涉及的列表类型:
permute (exclude x list)
类型为[[a]]
,因为类型签名为permute
,因此
listProduct x (permute (exclude x list))
def的类型也是[[a]]
。属于listProduct
listProduct x list2 = map (x :) list2
综上所述,
f x = listProduct x (permute (exclude x list))
返回[[a]]
,但是
permute list = map f list
将f
应用于[a]
的所有元素,返回一个[[a]]]]
,
这不是permute
的正确返回类型
如何修复
[[a]]]
转换为[[a]]]
Eq a
约束,因为您在exclude
中使用了/=x
[]
有一个排列。(事实上,0!=1,而不是0)对任何可能感兴趣的人来说——为了解决这个问题,我需要一种方法来模拟命令式编程的迭代,因此,一个循环列表建议了它自己(本质上,我一直在尝试模拟我曾经用javascript编写的解决方案,该解决方案涉及我描述的相同过程,唯一的例外是我利用了for循环)
permute[]=[]]
排列列表=[h:tail | h这样做的“正确”方法是将列表项的拾取和排除合并到一个纯粹的位置操作中select::[a]->[(a[a])]
:
顺便说一句,如果您不自己指定类型签名,它将编译并向您报告[a]->[[[a]]]]
类型
更重要的是,通过将/=
引入到图片中,您不需要对列表中的项进行Eq a
约束:permute::(Eq a)=>[a]->[[a]]
它在某种程度上为您调试,说它期望f
是类型a->[a]的函数,但得到的是类型a->[[a]]listProduct
任何东西看起来都应该返回一个[[a]]
,这将使f
接受参数x
,并返回一个[[a]]
。或许可以尝试独立地对每个函数进行实验,以确保它执行您希望它执行的操作。吉拉德,为什么f应该是(a->[a]类型?根据map的定义,似乎f有权映射到完全多态类型-map::(a->b)->[a]->[b]map f[]=[]map f(x:xs)=f x:map f xs
您应该在f
、exclude
和listProduct
上放置类型签名。当您有类型签名时,编译器错误将为您提供更多关于错误位置的线索。@criticalImperitive通常是一个好主意,尽管在这种特殊情况下需要ScopedTypeVariables
扩展,实际上没有任何帮助。嘿,所以我不确定我是否同意最后的评论。我们将f
应用于列表中的每个元素,而不是列表作为一个整体;也就是说,我们将f
应用于a
类型的值,而不是[a]
。至少这是我的意图。因此我们应该返回[[a]]
,而不是[[a]]]
@DanSok,如果f
为列表的每个元素返回[[a]]
,则映射f列表的结果是[[a]]
。
permute [] = [[]]
permute list = [h:tail | h <- list, tail <- (permute (exclude h list))]
where
exclude x = filter (/= x)
import Control.Arrow (second)
-- second f (a, b) = (a, f b)
select [] = []
select (x:xs) = (x,xs) : map (second (x:)) (select xs)
permute [] = [[]] -- 1 permutation of an empty list
permute xs = [x : t | (x,rest) <- select xs, t <- permute rest]
> let exclude e list1 = filter (/= e) list1
> let listProduct x list2 = map (x :) list2
> let f x = listProduct x (permute (exclude x list))
<interactive>:1:25: Not in scope: `permute' -- permute is not defined yet!!
<interactive>:1:44: Not in scope: `list' -- need to pass 'list' in
> let f list x = listProduct x (undefined (exclude x list))
--------- -- use a stand-in for now
> let permute [] = [] ; permute list = map (f list) list
> :t permute ---
permute :: (Eq t) => [t] -> [[[t]]] -- one too many levels of list!
> let permute [] = [] ; permute list = concatMap (f list) list
> :t permute ---------
permute :: (Eq t) => [t] -> [[t]] -- much better