2017-01-29 34 views
1

寫這樣的實例聲明工作正常:與類型變量

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

你不能,至少沒有直接。你可以爲'Either'做一個'newtype'包裝器。 – melpomene

回答

6

你不能,你不應該。如果你能做到這一點,那麼知道fmap (+1) (Left 1)應該是Left 1還是Left 2會更困難。

Bifunctor

這就是說,你正在尋找(動作,可以在任何一方被映射到)的抽象存在,被稱爲Bifunctor。然後,根據您是否想映射在Left S或在Right S,您使用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新類型中,這會找到第二個類型變量的函子實例。你仍然依賴於一個事實,即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