带有类型变量的实例声明

时间:2017-01-29 03:21:01

标签: haskell types typeclass functor bifunctor

写这样的东西很好:

data Either a b = Left a | Right b

instance Functor (Either a) where
    fmap _ (Left x) = Left x
    fmap f (Right x) = Right (f x)

现在让我说我要反转它,左边将f应用于值:

instance Functor (Either a) where
    fmap _ (Right x) = Right x
    fmap f (Left x) = Left (f x)

这不编译,我想我需要像Functor (Either _ b)这样的东西,我该怎么做?

1 个答案:

答案 0 :(得分:6)

你不能,你也不应该这样做。如果你能做到这一点,那么要知道fmap (+1) (Left 1)Left 1还是Left 2会更加困难。

Bifunctor

也就是说,你正在寻找的抽象(可以在任何一方映射的东西)存在,并被称为Bifunctor。然后,根据您是要映射Left还是Right,您可以使用firstsecond

ghci> first (+1) (Left 1)
Left 2
ghci> second (+1) (Left 1)
Left 1
ghci> first (+1) (Right 1)
Right 1
ghci> second (+1) (Right 1)
Right 2

Flip

或者,如果您只想坚持fmap而不是被firstsecond打扰,您可以将数据类型包装在Flip newtype中,具有查找第二个类型变量的仿函数实例的效果。您仍然依赖于EitherBifunctor这一事实,但您可以避免firstsecond

ghci> fmap (+1) (Flip (Left 1))
Flip (Left 2)
ghci> fmap (+1) (Left 1)
Left 1
ghci> fmap (+1) (Flip (Right 1))
Flip (Right 2)
ghci> fmap (+1) (Right 1)
Right 1