如何惯用地在[任一个]上使用bimap?也许还可以使用两个函数来映射[Either]的元素

时间:2018-08-02 18:21:17

标签: haskell

如何以更加惯用的方式在Either a b列表中应用两个功能(我想它可能正确地应用了bimap)? (不使用instance ... where,因为我希望灵活使用不同f g功能的“一次性”应用程序-> biEitherTransformGeneratorbiEitherFmap允许单线)

我尝试使用bimap将两个函数映射到Either a b的列表上:

biEitherTransformGenerator :: (a->c) -> (b->d) -> Either a b -> Either c d
biEitherTransformGenerator f g (Left x) = Left $ f x
biEitherTransformGenerator f g (Right x) = Right $ g x
biEitherFmap :: (Functor container) => (a->c) -> (b->d) -> container (Either a b) -> container (Either c d)
biEitherFmap f g = fmap $ biEitherTransformGenerator f g
el = [Left 5, Right "foo", Left 10, Right "bar"]:: [Either Int [Char]]
main = do
    print el
    let l1 = fmap (biEitherTransformGenerator (*2) (++"!!!")) el
    print l1
    let l2 = biEitherFmap (*2) (++"!!!") el
    print l2
    print $ l1 == l2
    -- let l3 = fmap (bimap (*2) (++"!!!")) el
    -- print l3

runhaskell DoubleFunctor.hs的输出:

[Left 5,Right "foo",Left 10,Right "bar"]
[Left 10,Right "foo!!!",Left 20,Right "bar!!!"]
[Left 10,Right "foo!!!",Left 20,Right "bar!!!"]
True

每次我取消对最后两行的注释:

let l3 = fmap (bimap (*2) (++"!!!")) el
print l3

我得到:

DoubleFunctor.hs:14:20: error:
    Variable not in scope:
      bimap
        :: (Integer -> Integer)
           -> ([Char] -> [Char]) -> Either Int [Char] -> b
   |
14 |     let l3 = fmap (bimap (*2) (++"!!!")) el
   |                    ^^^^^

我想要实现的目标:fmap (biEitherTransformGenerator f g) listOfEitherbiEitherFmap f g listOfEither的更惯用的方式。

1 个答案:

答案 0 :(得分:5)

Bifunctor类不属于Prelude;您需要先从Data.Bifunctor导入。 (取决于您的安装,该模块可能由base库提供,或者您可能需要先安装bifunctors库。)

Prelude> :t bimap

<interactive>:1:1: error: Variable not in scope: bimap
Prelude> import Data.Bifunctor
Prelude Data.Bifunctor> :t bimap
bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d
Prelude Data.Bifunctor> el = [Left 5, Right "foo", Left 10, Right "bar"]
Prelude Data.Bifunctor> fmap (bimap (*2) (++"!!!")) el
[Left 10,Right "foo!!!",Left 20,Right "bar!!!"]