Haskell中的子类型多态 [英] Subtype polymorphism in Haskell

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

问题描述

构建GUI小部件类的层次结构几乎是面向对象编程的标准练习。你有某种类型的抽象 Widget 类,其中包含可包含其他窗口小部件的窗口小部件的抽象子类,然后你可以获得更多的支持文本显示的窗口小部件的抽象类,支持作为输入焦点的小部件,具有布尔状态的小部件,直至实际的具体类,例如按钮,滑块,滚动条,复选框等。

我的问题是:在Haskell中做这件事的最好方法是什么?



有很多事情可以使构建Haskell GUI变得困难,但是不是我的问题的一部分。在Haskell中进行交互式I / O是稍微棘手的。实现一个GUI几乎总是意味着编写一个封装到极低级别的C或C ++库。写这种包装的人往往会逐字复制现有的API(大概是所有知道包装好的图书馆都会有家的人)。这些问题目前并不令我感兴趣。我完全感兴趣的是如何最好地为Haskell中的亚型多态性建模。



我们想要从我们的假设的GUI库中获得什么样的属性?那么,我们希望可以随时添加新的窗口小部件类型。 (换句话说,一组封闭的可能的小部件是不好的。)我们希望尽量减少代码重复。 (有很多的widget类型!)理想情况下,我们希望能够在必要时规定一个特定的widget类型,但也能够处理任何 widget的集合键入如果需要。



以上所有内容在任何自尊的OO语言中都是微不足道的。但是在Haskell中做这件事的最好方法是什么?我可以想到几种方法,但我不确定哪一种方法是最好的。 解决方案

,比如子类型多态,可以在Haskell中完成,你可以查看 OOHaskell 。这再现了各种强大的OOP类型系统的语义,保持了大多数类型的推断。实际的数据编码没有被优化,但我怀疑类型系列可能允许更好的演示。



可以使用类型类来对接口层次结构(例如Widget)进行建模。添加新的实例是可能的,所以这组具体的小部件是打开的。如果你想要一个可能的小部件的具体列表,那么GADT可以是一个简洁的解决方案。



子类的特殊操作是向上转换和向下转换。

这首先需要有一个Widgets集合,通常的结果是使用存在类型。如果您阅读 HList图书馆的所有位,还有其他有趣的解决方案。向上转换非常简单,编译器可以确定所有的转换在编译时都是有效的。向下转换本质上是动态的,需要一些运行时类型信息支持,通常是Data.Typeable。给定类似于Typeable的向下转换只是另一个类型的类,结果用Maybe来表示失败。



大部分代码都与样板相关,但是QusiQuoting和Templating可以减少这一点。



我还没有探索新的约束类型和类型,但是它们增强了对于向上转换和向下转换的存在解决方案。


Building a hierarchy of GUI widget classes is pretty much a standard exercise in object-oriented programming. You have some sort of abstract Widget class, with an abstract subclass for widgets that can contain other widgets, and then you have a profusion of further abstract classes for widgets that support textual display, widgets that support being the input focus, widgets that have a boolean state, right down to actual concrete classes such as buttons, sliders, scrollbars, check boxes, etc.

My question is: What is the best way to do this in Haskell?

There are a number of things that make building a Haskell GUI difficult, but are not part of my question. Doing interactive I/O is mildly tricky in Haskell. Implementing a GUI almost always means writing a wrapper to an extremely low-level C or C++ library. And people writing such wrappers tend to copy the existing API verbatim (presumably so anybody who knows the wrapped library will feel at home). These problems do not interest me at the moment. I'm interested purely in how best to model subtype polymorphism in Haskell.

What kind of properties would we want from our hypothetical GUI library? Well, we want it to be possible to add new widget types at any time. (In other words, a closed set of possible widgets is no good.) We want to minimise code duplication. (There are a lot of widget types!) Ideally we want to be able to stipulate one specific widget type when necessary, but also to be able to handle collections of any widget type if needed.

All of the above is of course trivial in any self-respecting OO language. But what is the best way to do this in Haskell? I can think of several approaches, but I'm not sure which one would be "best".

解决方案

To understand what OOP, such as subtype polymorphism, can be done in Haskell you can look at OOHaskell. This reproduces the semantics of a variety of powerful OOP type systems, keeping most type inference. The actual data encoding was not being optimized, but I suspect type families might allow better presentations.

Modelling the interface hierarchy (e.g. Widget) can be done with type classes. Adding new instances is possible and so the set of concrete widgets is open. If you want a specific list of possible widgets then GADTs can be a succinct solution.

The special operation with subclasses is upcasting and downcasting.

This is first needed to have a collection of Widgets, and usual result is to use existential types. There are other interesting solutions if you read all the bits of the HList library. The upcasting is fairly easy and the compiler can be certain that all casts are valid at compilation time. The downcasting is inherently dynamic and requires some run-time type information support, usually Data.Typeable. Given something like Typeable the downcasting is just another type class, with the result wrapped in Maybe to indicate failure.

There is boilerplate associated with most of this, but QusiQuoting and Templating can reduce this. The type inference can still largely work.

I have not explored the new Constraint kinds and types, but they make augment the existential solution to upcasting and downcasting.

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

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