为什么不能 Haskell 推导出这种类型
Why can’t Haskell deduce this type
我一直在尝试编写一个程序来实现任意域上的多项式,一种数学结构。我选择 Haskell 作为编程语言,并使用了 GADTs
语言扩展。但是,我不明白为什么GHCi不能推导出a
的约束。
上下文:
-- irreducible.hs
{-# LANGUAGE GADTs #-}
infixl 6 .+
infixl 7 .*
class Ring a where
(.+) :: a -> a -> a
(.*) :: a -> a -> a
fneg :: a -> a
fzero :: a
funit :: a
class (Ring a) => Field a where
finv :: a -> a
data Polynomial a where
Polynomial :: (Field a) => [a] -> Char -> Polynomial a
instance (Show a) => Show (Polynomial a) where
show (Polynomial (a0:ar) x)
= show a0
++ concatMap (\(a, k) -> "+" ++ show a ++ x:'^':show k) (zip ar [0..])
show (Polynomial [] _) = show (fzero::a)
解释:环是定义了加法和乘法的东西,其中加法形成一个(实际上是阿贝尔)群,乘法形成一个幺半群。域是一个定义了乘法倒数的环。字段上的多项式由一系列系数和一个字符表示。字符,例如 'x'
,表示此多项式是关于未知变量 x
的。对于写为 Polynomial [] 'x'
的零多项式,我希望它显示基础字段的零元素。
在 GHCi 运行 之后,我得到了这个:
irreducible.hs:59:28: error:
• Could not deduce (Show a0) arising from a use of ‘show’
from the context: Show a
bound by the instance declaration at irreducible.hs:55:10-40
or from: Field a
bound by a pattern with constructor:
Polynomial :: forall a. Field a => [a] -> Char -> Polynomial a,
in an equation for ‘show’
at irreducible.hs:59:9-23
The type variable ‘a0’ is ambiguous
These potential instances exist:
instance (Show a, Show b) => Show (Either a b)
-- Defined in ‘Data.Either’
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
...plus 25 others
...plus 87 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: show (fzero :: a)
In an equation for ‘show’:
show (Polynomial [] _) = show (fzero :: a)
In the instance declaration for ‘Show (Polynomial a)’
|
59 | show (Polynomial [] _) = show (fzero::a)
| ^^^^^^^^^^^^^^^
irreducible.hs:59:34: error:
• Could not deduce (Ring a1) arising from a use of ‘fzero’
from the context: Show a
bound by the instance declaration at irreducible.hs:55:10-40
or from: Field a
bound by a pattern with constructor:
Polynomial :: forall a. Field a => [a] -> Char -> Polynomial a,
in an equation for ‘show’
at irreducible.hs:59:9-23
Possible fix:
add (Ring a1) to the context of
an expression type signature:
forall a1. a1
• In the first argument of ‘show’, namely ‘(fzero :: a)’
In the expression: show (fzero :: a)
In an equation for ‘show’:
show (Polynomial [] _) = show (fzero :: a)
|
59 | show (Polynomial [] _) = show (fzero::a)
|
下面重点说一下有问题的部分:
instance (Show a) => Show (Polynomial a) where
show (Polynomial (a0:ar) x) = show a0 ++ [...]
show (Polynomial [] _) = show (fzero::a)
在我看来,Polynomial a
保证 a
是 Field
的实例,这意味着 a
是 Ring
的实例。所以调用fzero::a
,就像42::Int
一样,应该是合理的。此外,我已经写了Show a
作为约束,而Polynomial a
的构造函数具有Polynomial [a] Char
的形状,因此它也应该知道a0
的类型是[的实例=30=].
显然,解释器的想法不同。我哪里弄错了?
来自 arrowd 的评论:
代码没问题,但是需要ScopedTypeVariables
扩展,这使得fzero :: a
中的类型变量a
引用了前面介绍的a
.
我一直在尝试编写一个程序来实现任意域上的多项式,一种数学结构。我选择 Haskell 作为编程语言,并使用了 GADTs
语言扩展。但是,我不明白为什么GHCi不能推导出a
的约束。
上下文:
-- irreducible.hs
{-# LANGUAGE GADTs #-}
infixl 6 .+
infixl 7 .*
class Ring a where
(.+) :: a -> a -> a
(.*) :: a -> a -> a
fneg :: a -> a
fzero :: a
funit :: a
class (Ring a) => Field a where
finv :: a -> a
data Polynomial a where
Polynomial :: (Field a) => [a] -> Char -> Polynomial a
instance (Show a) => Show (Polynomial a) where
show (Polynomial (a0:ar) x)
= show a0
++ concatMap (\(a, k) -> "+" ++ show a ++ x:'^':show k) (zip ar [0..])
show (Polynomial [] _) = show (fzero::a)
解释:环是定义了加法和乘法的东西,其中加法形成一个(实际上是阿贝尔)群,乘法形成一个幺半群。域是一个定义了乘法倒数的环。字段上的多项式由一系列系数和一个字符表示。字符,例如 'x'
,表示此多项式是关于未知变量 x
的。对于写为 Polynomial [] 'x'
的零多项式,我希望它显示基础字段的零元素。
在 GHCi 运行 之后,我得到了这个:
irreducible.hs:59:28: error:
• Could not deduce (Show a0) arising from a use of ‘show’
from the context: Show a
bound by the instance declaration at irreducible.hs:55:10-40
or from: Field a
bound by a pattern with constructor:
Polynomial :: forall a. Field a => [a] -> Char -> Polynomial a,
in an equation for ‘show’
at irreducible.hs:59:9-23
The type variable ‘a0’ is ambiguous
These potential instances exist:
instance (Show a, Show b) => Show (Either a b)
-- Defined in ‘Data.Either’
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
...plus 25 others
...plus 87 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: show (fzero :: a)
In an equation for ‘show’:
show (Polynomial [] _) = show (fzero :: a)
In the instance declaration for ‘Show (Polynomial a)’
|
59 | show (Polynomial [] _) = show (fzero::a)
| ^^^^^^^^^^^^^^^
irreducible.hs:59:34: error:
• Could not deduce (Ring a1) arising from a use of ‘fzero’
from the context: Show a
bound by the instance declaration at irreducible.hs:55:10-40
or from: Field a
bound by a pattern with constructor:
Polynomial :: forall a. Field a => [a] -> Char -> Polynomial a,
in an equation for ‘show’
at irreducible.hs:59:9-23
Possible fix:
add (Ring a1) to the context of
an expression type signature:
forall a1. a1
• In the first argument of ‘show’, namely ‘(fzero :: a)’
In the expression: show (fzero :: a)
In an equation for ‘show’:
show (Polynomial [] _) = show (fzero :: a)
|
59 | show (Polynomial [] _) = show (fzero::a)
|
下面重点说一下有问题的部分:
instance (Show a) => Show (Polynomial a) where
show (Polynomial (a0:ar) x) = show a0 ++ [...]
show (Polynomial [] _) = show (fzero::a)
在我看来,Polynomial a
保证 a
是 Field
的实例,这意味着 a
是 Ring
的实例。所以调用fzero::a
,就像42::Int
一样,应该是合理的。此外,我已经写了Show a
作为约束,而Polynomial a
的构造函数具有Polynomial [a] Char
的形状,因此它也应该知道a0
的类型是[的实例=30=].
显然,解释器的想法不同。我哪里弄错了?
来自 arrowd 的评论:
代码没问题,但是需要ScopedTypeVariables
扩展,这使得fzero :: a
中的类型变量a
引用了前面介绍的a
.