如何以更加惯用的方式在Either a b
列表中应用两个功能(我想它可能正确地应用了bimap
)? (不使用instance ... where
,因为我希望灵活使用不同f g
功能的“一次性”应用程序-> biEitherTransformGenerator
和biEitherFmap
允许单线)
我尝试使用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) listOfEither
或biEitherFmap f g listOfEither
的更惯用的方式。
答案 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!!!"]