【问题标题】:Haskell: AST reduction causing type issuesHaskell:AST减少导致类型问题
【发布时间】:2018-03-11 05:38:51
【问题描述】:

我有以下代码用于可扩展的 AST。我的目标是允许稍后使用 Expr 类添加更多表达式类型,而不是将所有类型都放在一个数据块中。

data Constant o = Constant o deriving (Show)
data Add l r o = Add (l o) (r o) deriving (Show)

class Expr e where
  simplify :: (Expr a, Num o) => (e o) -> (a o)

instance Expr Constant where
  simplify (Constant a) = Constant a

instance (Expr l, Expr r) => Expr (Add l r) where
  simplify (Add l r) = case (simplify l, simplify r) of
    (Conatant a, Constant b) -> Constant $ a + b
    (sl@_, sr@_) -> Add sl sr

我遇到了这些错误:

math.hs:10:27: error:
    • Couldn't match type ‘a’ with ‘Constant’
      ‘a’ is a rigid type variable bound by
        the type signature for:
          simplify :: forall (a :: * -> *) o.
                      (Expr a, Num o) =>
                      Constant o -> a o
        at math.hs:10:3-10
      Expected type: a o
        Actual type: Constant o
    • In the expression: Constant a
      In an equation for ‘simplify’: simplify (Constant a) = Constant a
      In the instance declaration for ‘Expr Constant’
    • Relevant bindings include
        simplify :: Constant o -> a o (bound at math.hs:10:3)

math.hs:15:21: error:
    • Couldn't match type ‘a’ with ‘Add l0 r0’
      ‘a’ is a rigid type variable bound by
        the type signature for:
          simplify :: forall (a :: * -> *) o.
                      (Expr a, Num o) =>
                      Add l r o -> a o
        at math.hs:13:3-10
      Expected type: a o
        Actual type: Add l0 r0 o
    • In the expression: Add sl sr
      In a case alternative: (sl@_, sr@_) -> Add sl sr
      In the expression:
        case (simplify l, simplify r) of { (sl@_, sr@_) -> Add sl sr }
    • Relevant bindings include
        sr :: r0 o (bound at math.hs:15:12)
        sl :: l0 o (bound at math.hs:15:6)
        simplify :: Add l r o -> a o (bound at math.hs:13:3)

我不明白为什么这不起作用。再说一次,我对 Haskell 还是很陌生,因为我在 OOP 领域花了近十年的时间。我希望有人可以让我对此有所了解。

我正在尝试在没有任何 GHC 扩展的情况下执行此操作,因为我想在开始添加更多内容之前了解原版语言。

【问题讨论】:

    标签: haskell


    【解决方案1】:
    class ... where
      simplify :: (Expr a, ...) => ... -> (a o)
    

    此声明意味着您需要能够为 Expr 类中的任何类型构造 a o,通过使用 simplify 选择。您不能在实例中指定具体类型。

    编辑:你可以在 Expr 中引入一个结构:

    class Expr e where
        ...
        constant :: a -> e a
        add :: e a -> e a -> e a
        ...
    

    然后使用这些。虽然像 (add _ _ :: Constant Int) 这样的表达式没有意义。

    你可以做的是指定具有依赖关系的类:

    class Simplify e1 e2 | e1 -> e2 where ...
    

    或类型族:

    class Simplify e where
        data Simplified e :: *
        ....
    

    他们需要相应的扩展,但你不应该害怕。这就是现代 Haskell。

    【讨论】:

    • 非常简洁。谢谢你。我想我会飞跃使用扩展。有趣的是,自 Haskell 98 以来这些扩展中有多少已经出现,而且它们还不仅仅是语言的标准。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-19
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-18
    • 2018-01-14
    相关资源
    最近更新 更多