调用高阶函数时出错

时间:2014-12-16 04:46:42

标签: haskell ghci

我写了一个更高阶的Haskell函数,如下所示,

higherOrderFun f p xs = (map f) (filter p xs)

适用于以下

higherOrderFun (\x -> 2 * x) odd [1..4]

but throws an error for

higherOrderFun sin odd [1..4]

这是堆栈跟踪:

No instance for (Show b0) arising from a use of ‘print’
The type variable ‘b0’ is ambiguous
Note: there are several potential instances:
  instance Show Double -- Defined in ‘GHC.Float’
  instance Show Float -- Defined in ‘GHC.Float’
  instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
    -- Defined in ‘GHC.Real’
  ...plus 23 others
In a stmt of an interactive GHCi command: print it

任何调试指针?

3 个答案:

答案 0 :(得分:7)

这里的问题是oddsin的概念互动。您不能使用非浮点sin,浮点数不能为odd(或even。为了探索的目的,GHCI试图给你带来怀疑的好处,因此它没有为higherOrderFun sin odd [1..4]的输出分配具体类型,而是倾向于推断出在概念上不存在的类型(即{ {1}})。当您尝试打印值时,这会回过头来咬你,因为不存在的推断类型当然可以没有(Integral b, Floating b) => [b]的实例。这不仅限于Show:任何尝试分配具体类型(调用show,手动分配例如odd等)都会失败。

GHC更挑剔。如果您将其粘贴在:: Double文件中并尝试编译它,GHC会抱怨,因为它无法推断出.hs的连贯类型

higherOrderFun

关于module Main where higherOrderFun f p xs = (map f) (filter p xs) main :: IO () main = do let x = higherOrderFun (\x -> 2 * x) odd [1..4] y = higherOrderFun (sin) odd [1..4] print (x, y) {- [1 of 1] Compiling Main ( /tmp/test.hs, /tmp/test.o ) /tmp/test.hs:8:29: No instance for (Floating b0) arising from a use of ‘sin’ The type variable ‘b0’ is ambiguous Relevant bindings include y :: [b0] (bound at /tmp/test.hs:8:9) Note: there are several potential instances: instance Floating Double -- Defined in ‘GHC.Float’ instance Floating Float -- Defined in ‘GHC.Float’ In the first argument of ‘higherOrderFun’, namely ‘(sin)’ In the expression: higherOrderFun (sin) odd [1 .. 4] In an equation for ‘y’: y = higherOrderFun (sin) odd [1 .. 4] /tmp/test.hs:8:34: No instance for (Integral b0) arising from a use of ‘odd’ The type variable ‘b0’ is ambiguous Relevant bindings include y :: [b0] (bound at /tmp/test.hs:8:9) Note: there are several potential instances: instance Integral Int -- Defined in ‘GHC.Real’ instance Integral Integer -- Defined in ‘GHC.Real’ instance Integral GHC.Types.Word -- Defined in ‘GHC.Real’ In the second argument of ‘higherOrderFun’, namely ‘odd’ In the expression: higherOrderFun (sin) odd [1 .. 4] In an equation for ‘y’: y = higherOrderFun (sin) odd [1 .. 4] /tmp/test.hs:8:38: No instance for (Enum b0) arising from the arithmetic sequence ‘1 .. 4’ The type variable ‘b0’ is ambiguous Relevant bindings include y :: [b0] (bound at /tmp/test.hs:8:9) Note: there are several potential instances: instance Enum Double -- Defined in ‘GHC.Float’ instance Enum Float -- Defined in ‘GHC.Float’ instance Integral a => Enum (GHC.Real.Ratio a) -- Defined in ‘GHC.Real’ ...plus 7 others In the third argument of ‘higherOrderFun’, namely ‘[1 .. 4]’ In the expression: higherOrderFun (sin) odd [1 .. 4] In an equation for ‘y’: y = higherOrderFun (sin) odd [1 .. 4] /tmp/test.hs:8:39: No instance for (Num b0) arising from the literal ‘1’ The type variable ‘b0’ is ambiguous Relevant bindings include y :: [b0] (bound at /tmp/test.hs:8:9) Note: there are several potential instances: instance Num Double -- Defined in ‘GHC.Float’ instance Num Float -- Defined in ‘GHC.Float’ instance Integral a => Num (GHC.Real.Ratio a) -- Defined in ‘GHC.Real’ ...plus three others In the expression: 1 In the third argument of ‘higherOrderFun’, namely ‘[1 .. 4]’ In the expression: higherOrderFun (sin) odd [1 .. 4] /tmp/test.hs:9:5: No instance for (Show b0) arising from a use of ‘print’ The type variable ‘b0’ is ambiguous Relevant bindings include y :: [b0] (bound at /tmp/test.hs:8:9) Note: there are several potential instances: instance Show Double -- Defined in ‘GHC.Float’ instance Show Float -- Defined in ‘GHC.Float’ instance (Integral a, Show a) => Show (GHC.Real.Ratio a) -- Defined in ‘GHC.Real’ ...plus 24 others In a stmt of a 'do' block: print (x, y) In the expression: do { let x = higherOrderFun (\ x -> ...) odd ... y = higherOrderFun (sin) odd ...; print (x, y) } In an equation for ‘main’: main = do { let x = ... ....; print (x, y) } -} "工作":当map sin [1..4]打印某些内容时,它map sin [1..4]没有相同的限制。 GHCI将简单推断odd[1..4]的列表并采取相应行动。

调试

调试此问题的最佳方式(我发现)是使用GHCI中的Double:t命令。 GHCI会议的一个例子:

:i

马上,这种类型看起来很可疑。应该没有Prelude PrettyGHCI> let higherOrderFun f p xs = (map f) (filter p xs) Prelude PrettyGHCI> :t higherOrderFun sin odd [1..4] higherOrderFun sin odd [1..4] :: (Integral b, Floating b) => [b] Integral的类型。我们可以使用Floating

进行检查
:i

我稍微清理了输出,所以在这里显而易见的是,Prelude PrettyGHCI> :i Floating instance Floating Float instance Floating Double Prelude PrettyGHCI> :i Integral instance Integral Integer instance Integral Int Floating中的类型没有重叠。

此时,您基本上有两个选择

  1. 放弃
  2. 说服好玩的类型
  3. 放弃不是一个有效的选择,所以我们说服这些类型玩得很好:

    Integral

    这给了我们一个很好的,有效的多态类型。 Prelude PrettyGHCI> :t higherOrderFun (sin . fromIntegral) odd [1..4] higherOrderFun (sin . fromIntegral) odd [1..4] :: Floating b => [b] FloatingFloat)的两种类型居民都有Double个实例,因此您的工作已完成。

    请注意,我们之所以这样做是因为所有Show类型都必须为FloatingFractional提供了一个函数FractionalfromRational :: Rational -> a类型必须为IntegralReal提供函数RealtoRational :: a -> Rational只是定义为fromIntegral :: (Num b, Integral a) => a -> b

答案 1 :(得分:3)

如果您看一下,sin的类型为sin :: Floating a => a -> a,但您的列表的类型为(filter odd [1..4]) :: Integral a => [a]。因此,您遇到了失败。

但是,

higherOrderFun (sin . fromIntegral) odd [1..4]

返回

[0.8414709848078965,0.1411200080598672]

干杯,祝你好运。

答案 2 :(得分:2)

odd仅适用于Integral值(instance类型类型Integral类型的值)。 sin仅适用于Floating个。 higherOrderFun sin odd [1..4]的类型是

>:t higherOrderFun sin odd [1..4]
higherOrderFun sin odd [1..4] :: (Integral b, Floating b) => [b]

要使用此功能,您需要一个同时具有IntegralFloating的类型,并且基本库中不存在任何类型(也不应该存在)。您可以使用Num

Floating类型的值设置任何Integral类型的值,从而设置任何fromIntegral :: (Integral a, Num b) => a -> b类型的值
>:t higherOrderFun  (sin . fromIntegral) odd [1..4]
higherOrderFun (sin . fromIntegral) odd [1..4] :: Floating b => [b]

这只需要Floating个实例来获得结果。 ghci将使用Double对此进行评估,Floating是需要Prelude> higherOrderFun (sin . fromIntegral) odd [1..4] [0.8414709848078965,0.1411200080598672] 实例的未知类型的默认值。

{{1}}