列表范围的类型:如何使我的函数更少多态?

时间:2012-06-29 17:22:28

标签: haskell polymorphism ghci typing

我有一个功能

sasiad (x,y) = [ (x+dx,y+dy) | dy <- [-1..1], dx <- [-1..1], x+dx >= 0, y+dy >= 0]

我不喜欢那个功能的类型。我希望它返回[(Int,Int)]而不是[(t,t1)] 是否有可能强迫ghci做到这一点?

2 个答案:

答案 0 :(得分:7)

您可以添加类型注释作为dave4420提及,但正常的方法是:

sasiad :: (Int, Int) -> [(Int, Int)]
sasiad (x,y) = [ (x+dx,y+dy) | dy <- [-1..1], dx <- [-1..1], x+dx >= 0, y+dy >= 0]

然而,有一个论点要求使用编译器推断的类型:

sasiad :: (Ord t1, Ord t, Num t1, Num t, Enum t, Enum t1) => (t, t1) -> [(t, t1)]

作为this blog entry argues,更复杂的类型具有优势。例如,函数的推断类型区分tt1这一事实意味着如果声明此类型,编译器将不会让您混淆参数;基本上,这种类型保证结果列表中对的第一个元素仅使用x计算,而第二个元素仅使用y计算。这是否是一个有用的不变量取决于你的程序。

另外,我不得不重构你的功能:

sasiad :: (Ord t1, Ord t, Num t1, Num t, Enum t, Enum t1) => (t, t1) -> [(t, t1)]
sasiad (x,y) = cross (generate x) (generate y)
    where generate x = filter (>=0) . map (\dx -> x+dx) $ [-1..1]

cross xs ys = [ (x,y) | x <- xs, y <- ys ]

答案 1 :(得分:2)

是的,添加类型注释:

sasiad (x,y) = [ (x+dx,y+dy) | dy <- [-1..1], dx <- [-1..1], x+dx >= 0, y+dy >= 0] :: [(Int, Int)]