自定义Functor实例:预期类型'* - > *',但'AST'有点'*'

时间:2017-07-21 10:52:04

标签: haskell functor abstract-data-type

我有这个相当简单的ADT:

data AST = Node String [AST]
     | Leaf String
     | Empty
    deriving (Show)

和这个Functor实例:

instance Functor AST where
    fmap f (Node s l) = Node (f s) (fmap f l)
    fmap f (Leaf s)   = Leaf (f s)
    fmap f Empty      = Empty

但是当我尝试编译它时,我得到了这个错误,我完全不明白:

Expected kind ‘* -> *’, but ‘AST’ has kind ‘*’
   • In the first argument of ‘Functor’, namely ‘AST’
     In the instance declaration for ‘Functor AST’

有谁知道为什么会这样?我无法在互联网上找到解决方案。

2 个答案:

答案 0 :(得分:4)

仿函数适用于类型构造函数:如果你给它一个AST,它希望看到:

data AST a = ...
--       ^ type parameter

我们也可以在Functor类的定义中看到这一点:

class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b

请注意,类头部的f具有“ kind * -> *这意味着它充当某种带有另一种类型的函数(第一个{ {1}})并生成一个类型(第二个*)。正如您所看到的,*将采用fmap类型的函数(我们无法控制a -> b是什么)。在您对b的定义中,我们只能提供fmap函数。

现在将String -> String作为仿函数没有多大意义,因为它不是一个仿函数。

然而,您可以轻松AST概括为

AST

如果您使用该类型,则data AST a = Node a [AST a] | Leaf a | Empty deriving (Show)等同于AST String的旧定义。

同样适用于列表AST(也是[])。列表的 - 定义是:

Functor

我们在列表中将data [] a = [] | a : [a] 定义为:

Functor

请注意我们状态instance Functor [] where fmap _ [] = [] fmap f (x:xs) = (f x) : (fmap f xs),但是Functor [a]

答案 1 :(得分:1)

Functors必须是多态的,即data AST a = ...。在这种情况下,这就是“种类”的含义。它希望AST不是一个类型,而是一个类型函数,它接受一个类型并返回一个类型。