这个Functor实例是如何实现的?

时间:2018-03-14 09:24:34

标签: haskell functor

data GenTree f a -- kind (* -> *) -> * -> *
    = Node (f (GenTree f a))
    | Leaf a

instance Functor f => Functor (GenTree f) where
    fmap f (Node ts) = Node (fmap (fmap f) ts)
    fmap f (Leaf x)  = Leaf (f x)

我不理解上面Functor实例中的fmap (fmap f) ts语句。有人可以解释为什么这样写吗?

1 个答案:

答案 0 :(得分:3)

如果您查看Node的结构,它包含f (GenTree f a),那么如果我们查看相关表达式的类型:

fmap f (Node ts) = Node (fmap (fmap f) ts)

f此处的类型为a -> b

ts的类型为f (GenTree f a),但我们应该知道此表达式中的f不是上面的函数,而是实际的类型构造函数。为了消除混淆,我们将上面的函数重命名为g,如下所示:

fmap g (Node ts) = Node (fmap (fmap g) ts)

现在,为了应用我们的函数g,我们需要保持a的实际值。我们知道我们的f类型构造函数有Functor个实例,因此如果我们将其映射到它,我们会得到GenTree f a

fmap (\tree -> ...) ts

现在我们有了GenTree,我们可以递归地调用fmap,这样我们就可以在某些时候到达离开并实际将函数应用于值,如果我们写的话在它的所有样板中,它看起来像这样:

fmap g (Node ts) = Node (fmap (\tree -> fmap g tree) ts)

所以从本质上说它是这样编写的,因为我们需要fmap类型构造函数和实际f上的GenTree