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

问题描述:

我有一个函数列表类型的范围:如何让我的函数更少多态?

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

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

+4

需要注意的是,如果你在'(INT,INT)'传递给你的函数,你将* *回来的'[ (Int,Int)]'。多态函数真的没有缺点。 – sepp2k

是,新增的类型注释:

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

您可以添加类型标注为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 ]