从IO a写一个函数 - > a?

pik*_*ika 2 haskell

使用函数getLine.

它有一种类型

getLine :: IO String
Run Code Online (Sandbox Code Playgroud)

如何从此IO值中提取String.更一般地说,我该如何转换它.

IO a
Run Code Online (Sandbox Code Playgroud)

对此:

a
Run Code Online (Sandbox Code Playgroud)

如果这是不可能的.为什么我不能这样做?

dan*_*iaz 10

在Haskell中,当您想要使用"陷入" IO的值时,您不会从中获取值IO.相反,您也要将要执行的操作放入其中IO!

例如,假设您要getLine :: IO String使用lengthPrelude中的函数来检查将产生多少个字符.

存在一个辅助函数fmap,当专门用于时IO,具有以下类型:

fmap :: (a -> b) -> IO a -> IO b
Run Code Online (Sandbox Code Playgroud)

它需要一个可以处理未被捕获的"纯"值IO的函数,并为您提供一个函数,该函数可以处理陷入的值IO.这意味着代码

fmap length getLine :: IO Int
Run Code Online (Sandbox Code Playgroud)

表示IO从控制台读取一行的动作,然后为您提供其长度.

<$>是一个中缀的同义词fmap,可以使事情变得更简单.这相当于上面的代码:

length <$> getLine
Run Code Online (Sandbox Code Playgroud)

现在,有时操作要与执行IO-trapped值本身返回IO-trapped值.简单的例子:你要写回你刚读过的字符串putStrLn :: String -> IO ().

在那种情况下,fmap还不够.您需要使用(>>=)运算符,该运算符在特殊情况下IO具有该类型IO a -> (a -> IO b) -> IO b.在外面的情况:

getLine >>= putStrLn :: IO ()
Run Code Online (Sandbox Code Playgroud)

使用(>>=)链式IO动作具有必要的顺序风格.有一种叫做"do-notation"的语法糖,它有助于以更自然的方式编写这样的顺序操作:

do line <- getLine
   putStrLn line
Run Code Online (Sandbox Code Playgroud)

请注意,<-这里不是运算符,而是由符号提供的语法糖的一部分.