Haskell类具有多态数据定义的实例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Haskell类具有多态数据定义的实例相关的知识,希望对你有一定的参考价值。

关于具有多态数据类型的类定义,我有一个问题。让我们说定义的数据类型是:

data BTree a = BLeaf a | BNode a (BTree a) (BTree a) deriving(Show)

假设我想要检索树根的值,但是在名为Tree的类的实例中:

class Tree a where
             getRoot:: a -> (?)  --<- Type of Leave value as return type

和一个实例:

instance Tree (BTree a) where
                        getRoot BLeaf a = a
                        getRoot BNode a _ _ = a

我无法弄清楚函数的类型(参见questionmark),因为它不是a而且类不知道实例的参数。

答案

使class Tree声明中的类型变量引用类型* -> *的类型构造函数,然后您可以引用getRoot类型签名中树的值的类型。

class Tree t where
    getRoot :: t a -> a

instance Tree BTree where
    getRoot (BLeaf a)     = a
    getRoot (BNode a _ _) = a

另一个稍微复杂的解决方案,允许树结构是善良的*将是使用multi-parameter type classfunctional dependencies

{-# LANGUAGE FunctionalDependencies, FlexibleInstances #-}

class Tree t a | t -> a where
    getRoot :: t -> a

instance Tree (BTree a) a where
    getRoot (BLeaf a)     = a
    getRoot (BNode a _ _) = a

或者你可以使用type family

{-# LANGUAGE TypeFamilies #-}

class Tree t where
    type Value t
    getRoot :: t -> Value t

instance Tree (BTree a) where
    type Value (BTree a) = a
    getRoot (BLeaf a)     = a
    getRoot (BNode a _ _) = a
另一答案

首先,请记住,你的BTree是一种类型的* -> *,这基本上意味着它需要另一种类型作为参数来创建 - 你的a。因此,将类的变量称为a也会导致混淆。让我们换一下outer来说明一点。

然后你有:

class Tree outer where
    getRoot :: ???

寻找找到该函数的类型。知道树型需要另一种类型,我们知道getRoot必须传递像BTree Int这样的变量中的outer inner。您希望函数返回具有该内部类型的内容,因此您的类将是:

class Tree outer where
    getRoot :: outer inner -> inner

现在这是有道理的!您将树传递给该函数,它会向您显示具有该内部类型的内容。

然后,您将像以前一样实现您的实例:

instance Tree (BTree a) where
    getRoot (BLeaf x)     = x
    getRoot (BNode x _ _) = x

以上是关于Haskell类具有多态数据定义的实例的主要内容,如果未能解决你的问题,请参考以下文章

继承和多态

java 代码片段

8.python面向对象基础(封装,继承,多态)

Python类的继承与多态详细介绍

面向对象理解,封装继承多态知识总结

python(类的封装调用/继承/多态)