可以部分应用仿函数

问题描述 投票:6回答:1

我正在尝试为以下类型实现fmap

data Tree a = Leaf a | Node a (Tree a) (Tree a) | Empty deriving (Eq,Show)
instance Functor Tree where
        fmap _ Empty=Empty
        fmap f (Leaf x)=Leaf (f x)
        fmap f (Node t left right)=Node (f t) left right

我一直遇到类型不匹配错误:

错误

* Couldn't match type `a' with `b'
      `a' is a rigid type variable bound by
        the type signature for:
          fmap :: forall a b. (a -> b) -> Tree a -> Tree b
        at Monad.hs:8:9-12
      `b' is a rigid type variable bound by
        the type signature for:
          fmap :: forall a b. (a -> b) -> Tree a -> Tree b
        at Monad.hs:8:9-12
      Expected type: Tree b
        Actual type: Tree a

为什么我会得到这个错误,但当我也将fmap应用于子节点时,它编译没有问题:

fmap f (Node t left right) = Node (f t) (fmap f left) (fmap f right)

这是否意味着a内的所有Tree-s必须以某种方式成为b-s?而我在第一种情况下只处理非仿函数? ^

haskell types functor
1个回答
8
投票

这是否意味着a内的所有Tree-s必须以某种方式成为b-s?而我在第一种情况下只处理非仿函数? ^

恩,那就对了。你正试图实现fmap :: (a -> b) -> Tree a -> Tree b,但是当你写:

fmap f (Node t left right) = Node (f t) left right

你试图用Node :: b -> Tree b -> Tree b -> Tree bf t :: bleft :: Tree a这些参数调用right :: Tree a。将Tree a变成Tree b的唯一方法是通过fmap f :: Tree a -> Tree b,这就是为什么:

fmap f (Node t left right) = Node (f t) (fmap f left) (fmap f right)

按预期工作。

© www.soinside.com 2019 - 2024. All rights reserved.