我写了一个更高阶的Haskell函数如下,
higherOrderFun f p xs = (map f) (filter p xs)
Run Code Online (Sandbox Code Playgroud)
它适用于以下情况
higherOrderFun (\x -> 2 * x) odd [1..4]
but throws an error for
higherOrderFun sin odd [1..4]
Run Code Online (Sandbox Code Playgroud)
这是堆栈跟踪:
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
Run Code Online (Sandbox Code Playgroud)
有没有调试指针?
这里的问题是概念的互动odd和sin.你不能采用sin非浮点数,浮点数不能odd(或者even就此而言).为了探索的目的,GHCI试图给你怀疑的好处,所以它没有为输出分配一个具体的类型higherOrderFun sin odd [1..4],更喜欢推断一个概念上不存在的类型(即(Integral b, Floating b) => [b]).当您尝试打印值时,这会回来咬你,因为不存在的推断类型(当然)没有实例Show.这不限于show:任何分配具体类型(调用odd,手动分配例如:: Double等)的尝试都失败.
GHC更挑剔.如果你把它粘在一个.hs文件中并尝试编译它,GHC会抱怨,因为它不能推断出一个连贯的类型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) }
-}
Run Code Online (Sandbox Code Playgroud)
关于map sin [1..4]"工作":在map sin [1..4]打印某些东西时,它没有相同的限制odd.GHCI将简单推断[1..4]是一个Doubles 列表并相应地采取行动.
调试的最好方法(我发现)是使用GHCI中的:t和:i命令.GHCI会议的一个例子:
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]
Run Code Online (Sandbox Code Playgroud)
马上,这种类型看起来很可疑.应该没有两种类型的Integral和Floating.我们可以查看:i:
Prelude PrettyGHCI> :i Floating
instance Floating Float
instance Floating Double
Prelude PrettyGHCI> :i Integral
instance Integral Integer
instance Integral Int
Run Code Online (Sandbox Code Playgroud)
我清理输出位,所以它应该是显而易见这里有在居住类型没有重叠Floating和Integral.
此时,您基本上有两种选择
放弃不是一个有效的选择,所以我们说服类型玩得很好:
Prelude PrettyGHCI> :t higherOrderFun (sin . fromIntegral) odd [1..4]
higherOrderFun (sin . fromIntegral) odd [1..4] :: Floating b => [b]
Run Code Online (Sandbox Code Playgroud)
这给了我们一个很好的,有效的多态类型.Floating(Float和Double)两种类型的居民都有Show实例,因此你的工作已经完成.
请注意,我们可以这样做的原因是因为所有Floating类型都是必需的Fractional.Fractional提供一个功能fromRational :: Rational -> a.Integral类型是必需的Real,并Real提供一个功能toRational :: a -> Rational.fromIntegral :: (Num b, Integral a) => a -> b简单地定义为fromRational . toRational.
| 归档时间: |
|
| 查看次数: |
180 次 |
| 最近记录: |