2012-06-29 25 views
1

我有一個函數列表類型的範圍:如何讓我的函數更少多態?

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

回答

2

是,新增的類型註釋:

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