当前位置: 首页 > 知识库问答 >
问题:

为什么Haskell不能推导出这种类型

姬正文
2023-03-14

我一直在尝试编写一个程序来实现任意域上的多项式,一种数学结构。我选择了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)
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)

在我看来,多项式A保证A字段实例,这意味着A的实例。所以调用fzero::a就像调用42::int一样,应该是合理的。此外,我已经编写了showa作为约束,并且多项式a的构造函数具有多项式[a]char的形状,因此它还应该知道a0的类型是show的实例。

显然,译员的想法不同。我哪里搞错了?

共有1个答案

高和通
2023-03-14

从Arrowd的评论来看:

代码很好,但需要ScopedTypeVariables扩展名,这使得FZero::A中的类型变量A引用前面介绍的A

 类似资料:
  • 我有一个奇怪的场景,当使用lambda表达式时,类型推断没有像我预期的那样工作。以下是我真实场景的近似值: 我在倒数第二行得到的编译错误是 方法booleanValue()未为类型Object定义 如果我将lambda转换为

  • 我试图从文件“paddle.JS”中导入一个JS类,以便在另一个文件“game.JS”中使用(没有使用JS库或框架,只是纯简单的VanillaJS),我似乎不明白为什么这个导入/导出不起作用。我看过太多的例子和教程,我完全按照他们说的做,但它就是不起作用。这可能是一个愚蠢的问题,但任何帮助都是感激的。 这是我正在学习的一个YT教程,我基本上是在Paddle.js的顶部添加“导出默认类Paddle”

  • 操场 此错误与 我本以为第15行的界限会满足第7行的界限。我错过了什么?

  • 问题内容: 我读到从Java 7开始,像在第一条语句中那样在右侧指定类型来创建Collections是不好的样式,因为编译器可以从左侧推断类型。 我的问题是,当像这样初始化列表时,编译器找不到类型,并且我收到未经检查的类型警告: 问题答案: 编译器不会 推断 类型,因为您正在实例化 raw 。但是它足够聪明,可以警告您在使用此(原始)对象时可能会出现问题。 值得一提的是此警告背后的原因。由于类型擦

  • 问题内容: 在Java 7和更高版本中,菱形通常可以像这样毫无问题地用于推断类型: 但是,它不能用于这样的匿名内部类: 为什么是这样?从逻辑上讲,在这种情况下,我绝对可以将类型推断为。做出该决定的逻辑上的理由是,实际上不能在匿名内部类上推断类型,还是出于其他原因而将其省略了? 问题答案: 在JSR-334中: 不支持将Diamond与匿名内部类一起使用,因为这样做通常需要扩展类文件签名属性以表示不

  • 对于特定的任务,我需要在可变数组中进行大量快速、单独的写操作。为了检查性能,我使用了以下测试: