hPutStrLn with IO String?

后端 未结 1 1767
小鲜肉
小鲜肉 2021-01-26 18:20

I have a function which i must use and it is named :

hPutStrLn

That function has a type :

hPutStrLn::Handle -> String -> IO ()<

相关标签:
1条回答
  • 2021-01-26 18:54

    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.

    0 讨论(0)
提交回复
热议问题