eps*_*lbe 8 string io int haskell
你好伟大的程序员在那里,
我正在使用haskell的第一步,并且有一个令我困惑的功能:
import Data.List.Split
getncheck_guesslist = do
line <- getLine
let tmp = splitOneOf ",;" line
map read tmp::[Int]
Run Code Online (Sandbox Code Playgroud)
splitOneOf在Data.List.Split中(我用cabal安装拆分安装它)
splitOneOf :: (Eq a)=> [a]->[a]->[[a]]
从错误我得到它有一些类型不正确 - 但不知道如何解决这个冲突,因为IO对我来说仍然是一个谜
我想读取用逗号或分号分隔的整数输入,并得到一个整数列表,这样:
提前感谢您的想法和提示 - 您的ε/ 2
por*_*ges 12
当您编写使用IO monad的函数时,要从函数返回的任何值也必须位于IO monad中.
这意味着[Int]
,您必须返回带有类型的内容,而不是返回带有类型的值IO [Int]
.要做到这一点,你可以使用return
"包装"值的函数IO
(它实际上适用于任何 monad).
只需更改最后一行以包装您的值return
,如下所示:
getncheck_guesslist = do
line <- getLine
let tmp = splitOneOf ",;" line
return (map read tmp :: [Int])
Run Code Online (Sandbox Code Playgroud)
在Haskell中执行此操作的"正确方法"是将IO与其他所有内容分开.您的代码的直接翻译将是这样的:
getncheck_guesslist :: IO [Int]
getncheck_guesslist = do line <- getLine -- get
return (check_guesslist line) -- check
check_guesslist :: String -> [Int]
check_guesslist line = let tmp = splitOneOf ",;" line
in map read tmp
Run Code Online (Sandbox Code Playgroud)
请注意,这getncheck_guesslist
只是一个IO动作.该函数没有输入参数,即使它确实需要(IO)输入的getLine
.
另请注意,这getncheck_guesslist
是对getLine
IO操作的简单修改.是不是有一个组合器可以让我推动一个函数来对monad中的值进行操作?停止.霍格时间!
我有一个功能(a -> b)
.我有一个输入类型的值,但它被卡在monad中m a
.我想在monad中执行函数,所以结果也不可避免地会卡在monad中m b
.把它们放在一起,我们hoogle (a -> b) -> m a -> m b
.瞧,这fmap
正是我们所寻求的.
get_guesslist = check_guesslist `fmap` getLine
-- or, taking it a step further
get_guesslist = (map read . splitOneOf ",;") `fmap` getLine :: IO [Int]
Run Code Online (Sandbox Code Playgroud)
最后要注意的是,无论何时使用类似名称somethingAndSomethingElse
编写方法,编写和调用的编码风格通常都会更好,something
并且somethingElse
作为两个单独的方法.对于最终版本,我只是将其重命名get_guesslist
,因为从概念上讲它就是它的作用.它得到了作为Ints列表的猜测.
作为最后的最后一点,我已经离开了baroap开始的地步.;)fmap
是一样的<$>
.
如果某个东西在IO
单子之内,你就不能把它带到纯粹的外部世界进行进一步处理。相反,您可以传递纯函数以在IO
.
最后,您的程序读取一些输入并写入一些输出,因此您的 main 函数将与 一起使用IO
,否则您将无法输出任何内容。不要读取IO String
和创建一个[Int]
,而是将消耗它的函数传递[Int]
到您的 main 函数中并在内部使用它do
。