带有IO字符串的hPutStrLn? [英] hPutStrLn with IO String?

查看:104
本文介绍了带有IO字符串的hPutStrLn?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个我必须使用的函数,它被命名为:
$ b $ p $ s $ c $ h

该函数有一个类型:

hPutStrLn :: Handle - >字符串 - > IO()



我想做的事情是使用shell命令行 grep 并获取输出并传递给 hPutStrLn 的字符串变量。



例如: p>

  tryA(arrIO(\ s  - > hPutDocument(\ h-> hPutStrLn h(readProcessgrep[ n,s,camera2.owl]))))

但问题是,我的readProcess有IO类型的字符串,如果我想使用函数 hPutStrLn ,它必须是一个字符串!
我不知道如何解决这个问题...
所以我有几个问题是:
- 我能从IO字符串中提取字符串吗?
- 如果我不行,是否有其他方法可以做到这一点?

hPutDocument函数

  hPutDocument ::(Handle  - > IO()) - > IO()
hPutDocument操作
| isStdout
= do
hSetBinaryMode stdout(不是textMode)
动作stdout
hSetBinaryMode stdout False
|否则
= do
句柄< - (if textMode
then openFile
else openBinaryFile
)dst WriteMode
动作句柄
hClose句柄

isStdout = null dst || dst == -

outFile = if isStdout
thenstdout
else show dst


解决方案>

最简单的方法是使用 do 表示法。你可以定义一个辅助函数传递给 hPutDocument

  doGrep: :手柄 - > IO()
doGrep h =
do
str< - readProcessgrep[-n,s,camera2.owl]
hPutStrLn h str

tryA(arrIO(\s-> hPutDocument doGrep))

想一想,它允许你将 IO字符串转换为字符串,但只能在 do 块的范围,并且整个 do 块的结尾有一个 IO 类型 - IO()在这种情况下。



code> IO字符串添加到任意上下文中的 String ,因为Haskell的类型系统旨在阻止您处理不纯的值从外部来源被视为纯粹 - IO 类型表示该值可能来自某种IO。



您也可以在调用hPutDocument时直接使用>> = 操作符(发音为bind):

  hPutDocument(\h-> readProcessgrep[-n,s,camera2.owl]
>>> = \str - > hPutrStrLn h str)

>> = 有这种类型:

 (>> =):: IO a  - > (a→IO b)→> IO b 

在这种特殊情况下, a = String b =()



所以这里>> = 将由 readProcess ... 产生的 IO String 传递给第二个参数,它是一个接收 String 并产生一个 IO()的函数。总体结果是由第二个函数产生的 IO()



符号 \str - > hPutStrLn h str 定义了一个以 str 作为参数的匿名函数(一个lambda),并产生 hPutStrLn h str



上面的 do 表示法实际上是翻译过的(desugared )到这个由编译器。



在这个特定的实例中,您还可以缩短 \str - >您可以使用反向绑定运算符 = <<<<< code>来产生尽可能接近原始代码的东西:

  hPutDocument(\ h  - > hPutStrLn h =   

缩短 \str - > hPutStrLn h str 因部分应用程序(currying)而工作。一个接受多个参数的函数可以给出其中的一些参数(按顺序),并返回一个需要剩余参数的函数。



hPutStrLn 的类型为 Handle - >字符串 - > IO() hPutStrLn h 具有类型字符串 - > IO(),只要 h 的类型为 Handle


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

hPutStrLn

That function has a type :

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

And i what i wanted to do, it was using a shell command line grep and get the output and transmit to the String variable of hPutStrLn.

For example:

 tryA (arrIO (\s -> hPutDocument (\h-> hPutStrLn h (readProcess "grep" ["-n",s,"camera2.owl"] ""))))

But the problem is, that my readProcess has type of IO String, which must be a String if i wanna use the function hPutStrLn! And i don't know how i can solve this... So i have a few questions which is : -Could i extract the String from IO String ? - If i can't, is there any other way to do that ?

hPutDocument function

hPutDocument      :: (Handle -> IO ()) -> IO ()
      hPutDocument action
          | isStdout
              = do
                hSetBinaryMode stdout (not textMode)
                action stdout
                hSetBinaryMode stdout False
          | otherwise
              = do
                handle <- ( if textMode
                            then openFile
                            else openBinaryFile
                          ) dst WriteMode
                action handle
                hClose handle

isStdout  = null dst || dst == "-"

outFile   = if isStdout
            then "stdout"
            else show dst

解决方案

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.

这篇关于带有IO字符串的hPutStrLn?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆