在Haskell中扩展数据类型 [英] Extending a datatype in Haskell

查看:101
本文介绍了在Haskell中扩展数据类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Haskell新手在这里。

我写了一个评估器,用于最小程序集的语言。

现在,我想扩展该语言以支持一些语法糖,然后我将回编来仅使用原语操作符。理想的是,我不想再次触摸评估模块。



在OO的做事方式中,我认为可以扩展原来的模块,以支持语法糖操作符,在这里提供翻译规则。



除此之外,我只能想到在这两个模块中重写数据类型构造函数他们不会发生名称冲突,并且从那里继续,好像它们是完全不同的东西,但这意味着一些冗余,因为我必须重复(只是用其他名称)操作员的共同点。同样,我认为这里的关键字是扩展

有没有实现这个功能的方法?



感谢您花时间阅读此问题。 这个问题被Phil Wadler命名为表达问题,用他的话说:
$ b


目标是按大小写定义数据类型,在那里你可以添加新的数据类型和数据类型的新功能,而无需重新编译现有代码,同时保留
静态类型的安全性。


具有可扩展数据类型的解决方案是使用类型类。



举一个例子,假设我们有一个简单的算术语言:

 数据Expr =添加Expr Expr | Mult Expr Expr | Const Int 
$ b $ run(Const x)= x
run(Add exp1 exp2)= run exp1 + run exp2
run(Mult exp1 exp2)= run exp1 * run exp2



例如

  ghci的>运行(Add(Mult(Const 1)(Const 3))(Const 2))
5

如果我们想以可扩展的方式实现它,我们应该切换到类型类型:

  class Expr a where 
run :: a - > Int


数据Const = Const Int

实例Expr Const其中
run(Const x)= x


data添加ab =添加ab

实例(Expr a,Expr b)=> Expr(Add ab)where
run(Add expr1 expr2)= run expr1 + run expr2


data Mult ab = Mult ab

instance( Expr a,Expr b)=> Expr(Mult ab)其中
run(Mult expr1 expr2)= run expr1 * run expr2

现在让我们扩展语言添加减法:

  data Sub ab = Sub ab 

instance(Expr a,Expr b)=> Expr(Sub ab)其中
run(Sub expr1 expr2)= run expr1 - run expr2

eg

  ghci>运行(Add(Sub(Const 1)(Const 4))(Const 2))
-1

有关此方法的更多信息,以及有关表达问题的更多信息,请查看Ralf Laemmel的视频 1 2 。然而,正如评论中注意到的,这个解决方案发生了变化语义。例如,表达式列表不再合法:

  [Add(Const 1)(Const 5),Const 6]  - 不检查

使用类型签名的副产品的更通用的解决方案在函数式珍珠数据类型点菜。另请参阅Wadler在论文中的评论

Haskell newbie here.

I wrote an evaluator for a minimal assembly-like language.

Now, I want to extend that language to support some syntactic sugar which, I will then compile back to use only the primitive operators. The ideia is that I do not want to touch the evaluator module again.

In the OO way of doing things, I think, one could extend the original module so to support the syntactic sugar operators, providing here the translation rules.

Other than that, I can only think of rewriting the datatype constructors in both modules so that they would not name-collide, and proceed from there, as if they were complete different things, but that implies some redundancy, for I would have to repeat (just with other names) the operators in common. Again, I think the keyword here is extend.

Is there a functional way of accomplishing this?

Thanks for taking the time to read this question.

解决方案

This problem was named "the expression problem" by Phil Wadler, in his words:

The goal is to define a data type by cases, where one can add new cases to the data type and new functions over the data type, without recompiling existing code, and while retaining static type safety.

One solution to have extensible data type is to use type classes.

As an example let's assume we have a simple language for arithmetics:

data Expr = Add Expr Expr | Mult Expr Expr | Const Int

run (Const x) = x
run (Add exp1 exp2)  = run exp1 + run exp2
run (Mult exp1 exp2) = run exp1 * run exp2

e.g.

ghci> run (Add (Mult (Const 1) (Const 3)) (Const 2))
5

If we wanted to implement it in an extensible way, we should switch to type classes:

class Expr a where
    run :: a -> Int


data Const = Const Int

instance Expr Const where
    run (Const x) = x


data Add a b = Add a b

instance (Expr a,Expr b) => Expr (Add a b) where
    run (Add expr1 expr2) = run expr1 + run expr2


data Mult a b = Mult a b

instance (Expr a, Expr b) => Expr (Mult a b) where
    run (Mult expr1 expr2) = run expr1 * run expr2

Now let's extend the language adding subtractions:

data Sub a b = Sub a b

instance (Expr a, Expr b) => Expr (Sub a b) where
    run (Sub expr1 expr2) = run expr1 - run expr2

e.g.

ghci> run (Add (Sub (Const 1) (Const 4)) (Const 2))
-1

For more info on this approach, and in general on the expression problem, check Ralf Laemmel's videos 1 and 2 on Channel 9.

However, as noticed in the comments, this solution changes the semantics. For example lists of expressions are no longer legal:

[Add (Const 1) (Const 5), Const 6] -- does not typecheck

A more general solution using coproducts of type signatures is presented in the functional pearl "Data types a la carte". See also Wadler's comment on the paper.

这篇关于在Haskell中扩展数据类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆