2015-09-10 39 views
1

我需要創建一個元組列表,每個元組代表一個帶有(x,y,height,width)的矩形。
隨着寬度不變,我需要將高度值加倍。函數應用了三個參數

必要的輸出:

> genRects 3 (0,0) 
[(0.0,0.0,5.5,5.5),(5.5,0.0,5.5,5.5),(11.0,0.0,5.5,5.5),(16.5,0.0,5.5,5.5)] 

我目前的代碼:

genRects :: Int -> (Int,Int) -> [(Float,Float,Float,Float)] 
genRects 0 _ = [] 
genRects n (x,y) = let height=5.5; width=5.5 in [(fromIntegral x, fromIntegral y, height, width)] genRects (n-1) (x+height, y) 

四處錯誤:

Couldn't match expected type `(Int->(Int, Int)-> [(Float, Float, Float, Float)]) 
            -> Int -> (Int, Int) -> [(Float, Float, Float, Float)]' 
       with actual type `[(Integer, Integer, Double, Double)]' 
    The function `[(fromIntegral x, fromIntegral y, height, width)]' 
    is applied to three arguments, 
    but its type `[(Integer, Integer, Double, Double)]' has none 
    In the expression: 
     [(fromIntegral x, fromIntegral y, altura, comp)] 
     genRects (n - 1) (x + x, y) 
    In the expression: 
     let 
     height= 5.5 
     width = 5.5 
     in 
     [(fromIntegral x, fromIntegral y, height, width)] 
      genRects (n - 1) (x + x, y) 
Failed, modules loaded: none. 

而且爲什麼它要翻一番,而不是浮動?

回答

6

看一看

[(fromIntegral x, fromIntegral y, height, width)] genRects (n-1) (x+height, y) 

這是沒有意義的。你所要做的就是創建一個矩形之一,利弊它到所有其他矩形的,所以你應該使用類似

(fromIntegral x, fromIntegral y, height, width): genRects (n-1) (x+height, y) 

然而,在作出這一改變後,你會看到

Couldn't match expected type `Int' with actual type `Float' 
In the second argument of `(+)', namely `height' 
In the expression: x + height 
In the second argument of `genRects', namely `(x + height, y)' 

這是有道理的,你試圖增加一個Float(5.5)的x值,你說的是一個Int。最簡單的解決方案是使用Float s代替x,y代替Int s。 所以,你可以改變你的代碼,

genRects :: Int -> (Float,Float) -> [(Float,Float,Float,Float)] 
genRects 0 _ = [] 
genRects n (x,y) = let height=5.5; width=5.5 in (x, y, height, width): genRects (n-1) (x+height, y) 

,並得到想要的結果。

1

[(fromIntegral x, fromIntegral y, height, width)] genRects (n - 1) (x + x, y) 

你申請列表,以三個參數。列表不是功能,不能像這樣應用。 GHC正在談論Double,因爲你已經混淆了它,當它不知道它應該處理什麼類型的浮點時,它默認爲Double。注意:除非你正在處理專門針對單精度浮點調整的算法,或者處理需要這種特殊庫函數的算法,或者使用它們的無箱陣列來節省空間,否則應該真的使用Double你的代碼。

2

任何時候你有它創建了一個功能的一些地方ñ是功能明確的參數n,問問自己,如果你能代替它寫成:

take n $ some_infinite_list 

其中some_infinite_list是表達式創建了一些無限的列表。

舉例來說,這裏是調用由genRects n (x,y)創建的模式:

genRects n (x,y) 
    calls genRects (n-1) (x+h,y)  -- h = height 
    calls genRects (n-2) (x+h+h, y) 
    calls genRects (n-3) (x+h+h+h, y) 
    ... 

因此,如果我們開始與序列:

xys = [ (x,y), (x+h, y), (x+h+h, y), (x+3*h, y), ... ] 

,並創建一個功能to4Tuple

to4Tuple :: (Int,Int) -> (Float,Float,Float,Float) 

將一對(x,y)映射到您的四元組浮點數w E能寫genRects爲:

genRects n (x0,y0) = take n $ map to4Tuple sys 
    where xys = [ (x,y0) | x <- [x0, x0+h .. ] ] 
     to4Tuple (x,y) = ...construct 4-tuple from x,y here... 

現在你已經避免明確遞歸在genRects定義。