【问题标题】:Why can’t Haskell deduce this type为什么 Haskell 不能推断出这种类型
【发布时间】:2019-05-06 03:02:55
【问题描述】:

我一直在尝试编写一个程序来在任意域上实现多项式,这是一种数学结构。我选择 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 保证aField 的一个实例,这意味着aRing 的一个实例。所以调用fzero::a,就像42::Int一样,应该是合理的。另外,我已经写了Show a作为约束,Polynomial a的构造函数有Polynomial [a] Char的形状,所以它也应该知道a0的类型是Show的一个实例。

显然,解释器的想法不同。我哪里做错了?

【问题讨论】:

  • 常见错误,搜索ScopedTypeVariables
  • @arrowd 谢谢!这对我有用。

标签: haskell algebra type-variables


【解决方案1】:

来自箭头的评论:

代码没问题,但是需要ScopedTypeVariables扩展,这使得fzero :: a中的类型变量a引用了之前介绍的a

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多