Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply a constructor in a do context in Haskell

Given the following declarations

data MyCustomString = MyCustomString String deriving (Show, Eq)

getSomeString :: IO String

I'd like to process the output of getSomeString into a IO MyCustomString in a do context:

do
    cs_one <- getSomeString
    cs_two <- getSomeString

    -- at this point, `cs_one` and `cs_two` are of type `String`
    -- how to construct them into `MyCustomString` instead with no additional lines?

However, getSomeString returns an String and not an MyCustomString. How could I use the MyCustomString constructor so that both cs_one and cs_two are, at this point in the code, of type MyCustomString ?

I've tried this to no avail:

-- this does not work
do
    MyCustomString cs_one <- getSomeString
    MyCustomString cs_two <- getSomeString

-- this neither
do
    cs_one <- MyCustomString getSomeString
    cs_two <- MyCustomString getSomeString
like image 408
Jivan Avatar asked Jan 23 '26 06:01

Jivan


2 Answers

The usual way is:

do
    cs_one <- MyCustomString <$> getSomeString
    cs_two <- MyCustomString <$> getSomeString

The <$> operator is a synonym for fmap and has the signature:

(<$>) :: Functor f => (a -> b) -> f a -> f b

Since monads are functors, it specializes to the monad IO as:

(<$>) :: (a -> b) -> IO a -> IO b

which applies a function "under" the IO monad, in this case turning your IO String into an IO MyCustomString.

like image 189
K. A. Buhr Avatar answered Jan 24 '26 21:01

K. A. Buhr


Since getSomeString returns an IO String, and the constructor expects a naked string, you can't just apply the constructor to the result of getSomeString

First you have to get that string actually produced, and then you can wrap it in the constructor:

do
    cs_one_str <- getSomeString
    let cs_one = MyCustomString cs_one_str
    ...

Or you can use the fmap function, which does the exact same thing as the snippet above:

    cs_one <- fmap MyCustomString getSomeString

Or its operator alias <$>:

    cs_one <- MyCustomString <$> getSomeString
like image 37
Fyodor Soikin Avatar answered Jan 24 '26 22:01

Fyodor Soikin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!