Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequencing bind with pure functions

Tags:

haskell

I often find myself wanting to insert regular functions into a "binded" sequence. Like in this contrived example:

getLine >>= lift (map toUpper) >>= putStrLn

I need to define the lift function lift :: (a -> b) -> a -> m b to make this work. Problem is I don't know of such a function, and Hoogle doesn't seem to either. I find this odd since this makes totally sense to me.

Now, there are probably other ways to make this work, but I like the way point-free style code allows me to scan the line in one pass to figure out what is happening.

let lift f x = return (f x) in
getLine >>= lift (map toUpper) >>= putStrLn

My question boils down to this: am I missing something or how come there isn't a function like lift. My experience in Haskell is still very limited, so I am assuming that most people solve this in a different way. Can someone explain to me the idiomatic way of solving this.

like image 977
Magnus Kronqvist Avatar asked Mar 15 '12 12:03

Magnus Kronqvist


People also ask

Why do pure functions have no side effects?

A pure function does not have side-effects and its result does not depend on anything other than its inputs. A pure function guarantees that for a given input it will produce the same output no matter how many times it is called.

What are the characteristics of pure function?

A function must pass two tests to be considered “pure”: Same inputs always return same outputs. No side-effects.

What is the difference between pure and impure function?

Pure functions return the same output if we use the same input parameters. However, impure functions give different outcomes when we pass the same arguments multiple times. Pure functions always return some results. Impure functions can execute without producing anything.


2 Answers

There are three idiomatic ways.

  1. Don't use bind; use the first hit on your Hoogle search instead:

    liftM (map toUpper) getLine >>= putStrLn
    

    There are a variety of alternative spellings of liftM, such as fmap or (<$>).

  2. Inline the lift function you defined:

    getLine >>= return . map toUpper >>= putStrLn
    
  3. Use the monad laws to fuse the last two binds in option 2:

    getLine >>= putStrLn . map toUpper
    
like image 70
Daniel Wagner Avatar answered Sep 17 '22 11:09

Daniel Wagner


Use the Functor instance in such cases:

> import Data.Char
> import Data.Functor
> map toUpper <$> getLine >>= putStrLn
foo
FOO
>
like image 27
Ionuț G. Stan Avatar answered Sep 17 '22 11:09

Ionuț G. Stan