haskell - Haskell 中的亚型多态性

标签 haskell polymorphism

构建 GUI 小部件类的层次结构几乎是面向对象编程中的标准练习。你有某种抽象 Widget类,具有可以包含其他小部件的小部件的抽象子类,然后您有大量支持文本显示的小部件的进一步抽象类,支持作为输入焦点的小部件,具有 bool 状态的小部件,一直到实际具体的类,例如按钮、 slider 、滚动条、复选框等。

我的问题是:在 Haskell 中执行此操作的最佳方法是什么?

有很多事情使构建 Haskell GUI 变得困难,但这不是我的问题的一部分。在 Haskell 中进行交互式 I/O 有点棘手。实现 GUI 几乎总是意味着为极低级别的 C 或 C++ 库编写包装器。编写此类包装器的人倾向于逐字复制现有的 API(大概是这样任何了解包装库的人都会有宾至如归的感觉)。目前我对这些问题不感兴趣。我完全感兴趣的是如何最好地在 Haskell 中建模子类型多态性。

我们希望从假设的 GUI 库中获得什么样的属性?好吧,我们希望可以随时添加新的小部件类型。 (换句话说,封闭的一组可能的小部件是不好的。)我们希望最大限度地减少代码重复。 (有很多小部件类型!)理想情况下,我们希望能够在必要时规定一种特定的小部件类型,而且还能够在需要时处理任何小部件类型的集合。

在任何自尊的 OO 语言中,上述所有内容当然都是微不足道的。但是在 Haskell 中最好的方法是什么?我可以想到几种方法,但我不确定哪一种是“最好的”。

最佳答案

wxHaskell GUI 库充分利用了 幻象类型 对小部件层次结构进行建模。

想法如下:所有小部件共享相同的实现,即它们是指向 C++ 对象的外部指针。但是,这并不意味着所有小部件都需要具有相同的类型。相反,我们可以像这样构建一个层次结构:

type Object a = ForeignPtr a

data CWindow a
data CControl a
data CButton a

type Window  a = Object  (CWindow a)
type Control a = Window  (CControl a)
type Button  a = Control (CButton a)

这样,Control A 类型的值也匹配类型 Window b ,因此您可以将控件用作窗口,但不能反过来。如您所见,子类型化是通过嵌套类型参数实现的。

有关此技术的更多信息,请参阅 Dan Leijen's paper on wxHaskell 中的第 5 节。 .

请注意,这种技术似乎仅限于小部件的实际表示是统一的情况,即始终相同。但是,我相信通过一些想法,它可以扩展到小部件具有不同表示的情况。

特别是,观察到面向对象可以通过在数据类型中包含方法来建模,就像这样
data CWindow a = CWindow
    { close   :: IO ()
    , ...
    }
data CButton a = CButton
    { onClick :: (Mouse -> IO ()) -> IO ()
    , ...
    }

子类型化可能会在这里节省一些样板,但这不是必需的。

关于haskell - Haskell 中的亚型多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12002979/

相关文章:

haskell - 在 Haskell Web 应用程序中管理加密随机数生成器

haskell - 如何在自定义servant处理程序中响应HTTP状态?

C++ 问题 : Class Promotion using derived class

ruby-on-rails - rails 4 : polymorphic set base class type instead of inherited

ruby-on-rails - 多态关联 Rails : Different primary_keys types (id & uuid)

ios - iOS 5 下的 Haskell : suppressing output

haskell - 表达式 fmap 的求值 (*3) (+5) 1

haskell - Haskell 中的类型错误

Haskell::如何创建任意长度的向量?

c++ - 如何在多态中调用子对象的重载函数?