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
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With