我现在正在和Haskell搞乱,为了我的生活,我无法弄清楚为什么以下有效......
square :: (Num a) => a -> a
square x = x * x
dx = 0.0000001
deriv1 :: (Fractional a) => (a -> a) -> (a -> a)
deriv1 g = (\x -> ((g (x + 2) - (g x)) / 0.0000001 ))
main = printf "res==%g %g\n" (square 5.12::Double) ((deriv1 square) 2::Float)
但这并不......
square :: (Num a) => a -> a
square x = x * x
dx = 0.0000001
deriv1 :: (Fractional a) => (a -> a) -> (a -> a)
deriv1 g = (\x -> ((g (x + 2) - (g x)) / dx ))
main = printf "res==%g %g\n" (square 5.12::Double) ((deriv1 square) 2::Float)
注意我这次在derv1函数中使用了dx
。我是Haskell的新手,所以任何关于类型的深入讨论都可能会让我快速地掠过我,我会死于旋转。我迫切需要一些类似命令性答案的东西,或者在我的Haskell职业生涯早期几乎肯定会失去我。
我收到的错误消息是:
Inferred type is less polymorphic than expected
Quantified type variable `a' is mentioned in the environment:
dx :: a (bound at sicp-1.40.hs:12:0)
When trying to generalise the type inferred for `deriv1'
Signature type: forall a. (Fractional a) => (a -> a) -> a -> a
Type to generalise: (a -> a) -> a -> a
In the type signature for `deriv1'
When generalising the type(s) for `deriv1'
答案 0 :(得分:6)
由于monomorphism restriction,您收到错误。由于您没有为dx
提供类型签名,因此在这种情况下最终会将其推断为Double
。您可以提供明确的多态签名,如
dx :: Fractional a => a
dx = 0.0000001
或者您可以通过在源文件的顶部包含此行来禁用单态限制
{-# LANGUAGE NoMonomorphismRestriction #-}
答案 1 :(得分:4)
避免结束单态限制的最好方法是将dx
置于本地:
deriv1 :: (Fractional a) => (a->a) -> a->a
deriv1 g = (\x -> ((g (x + dx) - (g x)) / dx ))
where dx = 0.0000001
请注意,我也为2
更改了dx
,这在您的定义中有点不对。 (不是编程方面,而是数学方面。)
deriv1 g x = (g (x + dx) - g x) / dx
Haskell会自动将其转换为lambda。
答案 2 :(得分:2)
由于单态限制,dx
的类型默认为Double。因此,当您在dx
中除以deriv1
时,Haskell会将另一个操作数推断为/
,结果也必须具有Double类型。但是,由于您的类型签名显示为a
,因此您会收到错误。
您可以通过明确声明dx
具有类型Fractional a => a
或禁用单态限制来解决此问题。