Is there a combinator that applies multiple functions to a single value in Haskell?

StackOverflow https://stackoverflow.com/questions/17899435

  •  04-06-2022
  •  | 
  •  

Pergunta

For example, suppose I have the following functions:

foo :: Monad f => f a
bar :: Monad f => a -> f b
baz :: Monad f => a -> f c
qux :: Monad f => a -> f d

And I only want to return the result of qux, e.g. g :: Monad f => f a -> f d, where g calls bar and baz for their side-effects, perhaps.

Is there a way to construct g without explicitly applying each function to the result of foo? Somewhat similar to how (&&&) works, or (<*>) I suppose.

Foi útil?

Solução 2

I'm assuming that a b c and d are in fact not supposed to be type variables and instead you meant more like

 data A
 data B
 data C
 data D

Because otherwise you're asking for a function of type forall a b. a -> b which is impossible to meaningfully create.

k = Kleisli
a &^& b = a &&& b >>> arr snd
g = runKleisli $ k bar &^& k baz &^& k quux

is a simple way to do this. it uses the kleisli arrow which wraps around a Monad to lift it into arrow land. I'm not aware of any nice combinators that accomplish &^& in a predefined way but it's pretty trivial to define.

The nice thing is that this scales trivially and is pointfree

 g = runKleisli $ k f &^& k f' &^& k f'' &^& k f''' ....

Outras dicas

Here's a possible solution using the Monad instance for ((->) r). This works nicely, and scales to as many function applications as neccessary.

g :: Monad m => m a -> m b
g foo = foo >>= bar .&. baz .&. qux
    where (.&.) = liftM2 (>>)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top