2015-09-10 42 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定义。