如果是模棱两可的类型,如何确定类型?
How to figure out the type if it is ambiguous type?
我是 Haskell 初学者,我在理解这一点上遇到了一些困难。我在这样的文件中定义了 2 个函数:
expr n x = (x ^ n)/(fact n)
fact n
| n == 0 = 1
| otherwise = n * fact (n - 1)
但是当我尝试 运行 说 expr 3 2
时,我不断收到这样的错误:
*Main> expr 3 2
<interactive>:31:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘print’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
...plus 22 others
...plus 19 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of an interactive GHCi command: print it
我检查了各种表达式的类型,我看到了这个:
*Main> :t (/)
(/) :: Fractional a => a -> a -> a
*Main> :t (^)
(^) :: (Integral b, Num a) => a -> b -> a
*Main> :t 3 ^ 6
3 ^ 6 :: Num a => a
*Main> :t fact
fact :: (Eq p, Num p) => p -> p
*Main> :t fact 3
fact 3 :: (Eq p, Num p) => p
*Main> :t 9 / 6
9 / 6 :: Fractional a => a
但是我不知道应该为我的函数提供什么类型来避免这种情况。我尝试为我的事实函数提供这样的类型,因为 (/) 需要 Fractional:
fact :: (Fractional a) => Int -> a
但是如果我尝试提供我的函数类型,该文件甚至不会加载到 ghci 中。如果有帮助,我可以 post 我尝试加载类型文件时收到的错误消息。
如果我尝试将类型添加到计算表达式时使用的显示,那也不起作用:
*Main> expr 3 2 :: String
<interactive>:37:1: error:
• No instance for (Fractional String) arising from a use of ‘expr’
• In the expression: expr 3 2 :: String
In an equation for ‘it’: it = expr 3 2 :: String
<interactive>:37:6: error:
• No instance for (Num String) arising from the literal ‘3’
• In the first argument of ‘expr’, namely ‘3’
In the expression: expr 3 2 :: String
In an equation for ‘it’: it = expr 3 2 :: String
*Main> expr 3 2 :: Integer
<interactive>:38:1: error:
• No instance for (Fractional Integer) arising from a use of ‘expr’
• In the expression: expr 3 2 :: Integer
In an equation for ‘it’: it = expr 3 2 :: Integer
如评论中所述,运算符 /
就像 + - * 一样,强制其两个操作数具有相同的类型(这也是结果的类型)。运算符 ^
是一个例外,其结果必须与其左操作数具有相同的类型。请注意,对于浮点类型,您还可以使用 Fortran 中的 **
求幂运算符。
在此 tutorial 中对规则进行了更详细的解释。
不幸的是,这意味着混合模式算术在 Haskell 中比在一些著名的命令式语言中更难获得。如果需要,可以使用转换函数fromIntegral :: (Integral a, Num b) => a -> b。它允许编译器插入一些适当的转换。
对于目前的情况,如果需要宽类型签名,可以这样实现,例如:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ExplicitForAll #-}
fact :: Integral nt => nt -> nt
fact n = if (n <= 0) then 1 else n * fact (n - 1)
expr :: forall nt ft. (Integral nt, Fractional ft) => nt -> ft -> ft
expr n x = (x ^ n) / ((fromIntegral (fact n)) :: ft)
测试 ghci
:
$ ghci
GHCi, version 8.6.5: http://www.haskell.org/ghc/ :? for help
λ>
λ> :load q65254539.hs
...
Ok, one module loaded.
λ>
λ> expr 2 3
4.5
λ> expr 2 pi
4.934802200544679
λ>
λ> expr 3 (4::Double)
10.666666666666666
λ>
我是 Haskell 初学者,我在理解这一点上遇到了一些困难。我在这样的文件中定义了 2 个函数:
expr n x = (x ^ n)/(fact n)
fact n
| n == 0 = 1
| otherwise = n * fact (n - 1)
但是当我尝试 运行 说 expr 3 2
时,我不断收到这样的错误:
*Main> expr 3 2
<interactive>:31:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘print’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
...plus 22 others
...plus 19 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of an interactive GHCi command: print it
我检查了各种表达式的类型,我看到了这个:
*Main> :t (/)
(/) :: Fractional a => a -> a -> a
*Main> :t (^)
(^) :: (Integral b, Num a) => a -> b -> a
*Main> :t 3 ^ 6
3 ^ 6 :: Num a => a
*Main> :t fact
fact :: (Eq p, Num p) => p -> p
*Main> :t fact 3
fact 3 :: (Eq p, Num p) => p
*Main> :t 9 / 6
9 / 6 :: Fractional a => a
但是我不知道应该为我的函数提供什么类型来避免这种情况。我尝试为我的事实函数提供这样的类型,因为 (/) 需要 Fractional:
fact :: (Fractional a) => Int -> a
但是如果我尝试提供我的函数类型,该文件甚至不会加载到 ghci 中。如果有帮助,我可以 post 我尝试加载类型文件时收到的错误消息。
如果我尝试将类型添加到计算表达式时使用的显示,那也不起作用:
*Main> expr 3 2 :: String
<interactive>:37:1: error:
• No instance for (Fractional String) arising from a use of ‘expr’
• In the expression: expr 3 2 :: String
In an equation for ‘it’: it = expr 3 2 :: String
<interactive>:37:6: error:
• No instance for (Num String) arising from the literal ‘3’
• In the first argument of ‘expr’, namely ‘3’
In the expression: expr 3 2 :: String
In an equation for ‘it’: it = expr 3 2 :: String
*Main> expr 3 2 :: Integer
<interactive>:38:1: error:
• No instance for (Fractional Integer) arising from a use of ‘expr’
• In the expression: expr 3 2 :: Integer
In an equation for ‘it’: it = expr 3 2 :: Integer
如评论中所述,运算符 /
就像 + - * 一样,强制其两个操作数具有相同的类型(这也是结果的类型)。运算符 ^
是一个例外,其结果必须与其左操作数具有相同的类型。请注意,对于浮点类型,您还可以使用 Fortran 中的 **
求幂运算符。
在此 tutorial 中对规则进行了更详细的解释。
不幸的是,这意味着混合模式算术在 Haskell 中比在一些著名的命令式语言中更难获得。如果需要,可以使用转换函数fromIntegral :: (Integral a, Num b) => a -> b。它允许编译器插入一些适当的转换。
对于目前的情况,如果需要宽类型签名,可以这样实现,例如:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ExplicitForAll #-}
fact :: Integral nt => nt -> nt
fact n = if (n <= 0) then 1 else n * fact (n - 1)
expr :: forall nt ft. (Integral nt, Fractional ft) => nt -> ft -> ft
expr n x = (x ^ n) / ((fromIntegral (fact n)) :: ft)
测试 ghci
:
$ ghci
GHCi, version 8.6.5: http://www.haskell.org/ghc/ :? for help
λ>
λ> :load q65254539.hs
...
Ok, one module loaded.
λ>
λ> expr 2 3
4.5
λ> expr 2 pi
4.934802200544679
λ>
λ> expr 3 (4::Double)
10.666666666666666
λ>