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

时间:2017-12-14 23:59:04

标签: haskell functional-programming polymorphism

我对有多态数据类型的类定义有疑问。让我们说定义的数据类型是:

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

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

2 个答案:

答案 0 :(得分:6)

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

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

*

或者您可以使用type family

{-# 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

答案 1 :(得分:1)

首先,请注意,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