2012-11-30 54 views
4

我想实现的law of cosines功能,这里的法律是我的代码:Haskell的实现余弦

cosC :: [a] -> a 
cosC sides 
    | length sides < 3   = 0 
    | otherwise     = (x^2 + y^2 - z^2)/(2 * x * y) 
    where x = head(tail(tail(sides))) 
     y = head(tail(sides)) 
     z = head(sides) 

,但我得到两个错误:

No instance for (Fractional a) 
arising from a use of `/' 
In the expression: (x^2 + y^2 - z^2)/(2 * x * y) 
In an equation for `cosC': 
    cosC sides 
     | length sides < 3 = 0 
     | otherwise = (x^2 + y^2 - z^2)/(2 * x * y) 
     where 
      x = head (tail (tail (sides))) 
      y = head (tail (sides)) 
      z = head (sides) 

No instance for (Num a) 
arising from the literal `2' 
In the first argument of `(*)', namely `2' 
In the first argument of `(*)', namely `2 * x' 
In the second argument of `(/)', namely `(2 * x * y)' 

编辑:我已经修复了上述余弦定律中的符号错误。感谢Daniel Fischer指出了这一点。

+4

你有一个符号错误,它应该是'(x^2 + y^2 - z^2)'的法律的余弦。 –

+0

斑点!非常感谢。 – User3419

回答

11

你试图计算数值结果出来一般类型a的,以及不可能工作。 (就像试图搭建一座桥梁,不仅适用于普通公路车辆,而且适用于一般的东西,例如太空船,摩天大楼,回形针和中子星)。就在Floating约束添加到:

cosC :: Floating a => [a] -> a 

,你可以执行任何你需要这样的计算的算术运算。 (Fractional对于此功能实际上已经足够了,但是您将无法计算出结果的arccos)。


无关您的问题,请注意,有一个更好的方法来分解表在Haskell:

cosC (x:y:z:_) = (x^2 + y^2 - z^2)/(2*x*y) 
cosC _ = 0 

等同于你的定义。你为什么将这些论点作为一个列表呢?这是Lisp-ish要做的事情,在Haskell我更喜欢

cosC :: Floating a => a -> a -> a -> a 
cosC x y z = (x^2 + y^2 - z^2)/(2*x*y) 
+2

非常感谢非常有用的答案!实际上,它是用于科学计算器程序的,我使用RPN和我的堆栈被表示为一个双精度列表 – User3419

+5

即使你的堆栈被表示为一个列表,它并不意味着每一个函数都必须在列表上运行,这样每个函数都必须处理列表太短的情况,等等 - 你可能会更好地使这个函数有三个参数,然后使用一些其他的通用函数,通用函数从堆栈中弹出三个值并传递给这个值。 – shachaf

+8

用于处理类似编译器消息并改进Has​​kell-fu的提示:如果您的函数上有类型签名,请尝试将它们注释掉,并注释掉其他任何可阻止编译代码的内容。然后将代码加载到GHCi中,并询问每个函数的类型(使用命令':t _functionName_')。你可能会发现你的一个函数的类型与你想象的不同。 – mhwombat

5

cosC :: Fractional a => [a] -> a

这是你可以找到(在ghci):

*Main> let fun [x, y, z] = (x * x + y * y + z * z)/(2 * x * y) 
*Main> :type fun 
fun :: Fractional a => [a] -> a 
+0

非常感谢!这也很有用,但上面的答案为可能有或已经有相同或类似问题的用户提供了更多信息。 – User3419

+1

@Hristo如果你保留list参数,那么我建议你从black_dragon的例子中学习使用模式匹配参数(注意'[x,y,z]'绑定x,y和z变量。 –

+0

@Hristo,但是,注意''[x,y,z]'没有给出与'x:y:z:_'或'head sides'' head(tail sides)'等同的行为,因为'[x,y, z]'只会匹配长度正好3的列表,而另外两个匹配长度至少为3. – huon