带有IO字符串的hPutStrLn? [英] hPutStrLn with IO String?
问题描述
我有一个我必须使用的函数,它被命名为:
$ 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屋!