Reputation: 41
I am using a String -> IO [x]
function in order to read in the contents of a file into a list where each element in the list is a word from the file.
However, I would like to use the the [x]
list as an input for another function. My issue is that I do not understand how to access the basic [x]
list rather than the IO [x]
list generated in my initial function. I have been getting around this for testing by using GHCI and using
k <- listRead "file.txt"
and then using that k
as input in my next function that only takes a list [x]
as input.
How can I use the "internal" list [x]
instead of the returned IO [x]
that my initial function returns?
Upvotes: 0
Views: 770
Reputation: 71119
Simply, put that line which you used in GHCi into a do
block:
do
k <- listRead "file.txt"
let r = yourPureFunction k
return r
In do
notation, for an x <- mx
line, whenever mx :: M a
for some Monad M
, we have x :: a
.
Thus yourPureFunction :: a -> b
is applied to the a
argument on the inside of M
, and the combined monadic value represented by the do
block has the type M b
, because return
has the type return :: b -> M b
, and the overall type of a do
block is the type of its last expression.
The above code happens to really be a higher-level syntax representation of / encodable as / (return . yourPureFunction) =<< listRead "file.txt"
which is also the same as yourPureFunction <$> listRead "file.txt"
(with (<$>) = fmap
), but that's besides the point.
Upvotes: 0
Reputation: 532063
This is what the Monad
type class is for.
foo :: String -> IO [SomeType]
bar :: [SomeType] -> IO SomeOtherType
then
baz :: String -> IO SomeOtherType
baz name = foo name >>= bar
(or after importing Control.Monad
, baz = foo >=> bar
).
If all you have is some function bar' :: [SomeType] -> SomeOtherType
, then you can define
bar :: [SomeType] -> IO SomeOtherType
bar = return . bar'
Note you can never actually "get" the value of type [SomeType]
; you can only create new IO actions that use the value once the IO action is executed.
Upvotes: 3