I have a function which i must use and it is named :
hPutStrLn
That function has a type :
hPutStrLn::Handle -> String -> IO ()<
The simplest approach is with do
notation. You could define an auxiliary function to pass to hPutDocument
:
doGrep :: Handle -> IO ()
doGrep h =
do
str <- readProcess "grep" ["-n",s,"camera2.owl"] ""
hPutStrLn h str
tryA (arrIO (\s -> hPutDocument doGrep))
One way to think of it is that it allows you to convert an IO String
to a String
, but only within the scope of the do
block, and the entire do
block ends up having an IO
type - IO ()
in this case.
You can't convert an IO String
to a String
in an arbitrary context, because Haskell's type system is designed to stop you from treating impure values that come from external sources being treated as pure - the IO
type indicates that the value may have come from doing some kind of IO.
You can also use the >>=
operator (pronounced "bind") directly in your call to hPutDocument:
hPutDocument (\h -> readProcess "grep" ["-n",s,"camera2.owl"] ""
>>= \str -> hPutrStrLn h str)
>>=
has this type:
(>>=) :: IO a -> (a -> IO b) -> IO b
In this particular case, a = String
and b = ()
.
So here >>=
takes the IO String
produced by readProcess ...
and passes it to the second argument, which is a function that takes a String
and produces an IO ()
. The overall result is the IO ()
produced by the second function.
The notation \str -> hPutStrLn h str
defines an anonymous function (a "lambda") that takes str
as an argument and produces the result of hPutStrLn h str
.
The do
notation above is actually translated ("desugared") to this by the compiler.
In this particular instance you can also shorten \str -> hPutrStrLn h str
to just hPutStrLn h
, and you could also use the reverse bind operator =<<
to produce something as close as possible to your original code:
hPutDocument (\h -> hPutStrLn h =<< readProcess "grep" ["-n",s,"camera2.owl"] "")
Shortening \str -> hPutStrLn h str
works because of partial application ("currying"). A function that takes multiple arguments can be just given some of them (in order), giving back a function that expects the remaining arguments.
Since hPutStrLn
has type Handle -> String -> IO ()
, hPutStrLn h
has type String -> IO ()
, so long as h
has type Handle
.