Haskell练习Mooc FI Do符号

Haskell Exercise Mooc FI Do notation

这是https://haskell.mooc.fi/训练

的练习
-- Ex 5: define the IO operation readUntil f, which reads lines from
-- the user and returns them as a list. Reading is stopped when f
-- returns True for a line. (The value for which f returns True is not
-- returned.)
--
-- Example in GHCi:
--   *Set11> readUntil (=="STOP")
--   bananas
--   garlic
--   pakchoi
--   STOP
--   ["bananas","garlic","pakchoi"]

readUntil :: (String -> Bool) -> IO [String]
readUntil f = todo

你能给我提供一个使用 do 表示法的提示/解决方案吗? 我刚开始使用 do 表示法,目前“条件逻辑”和循环对我来说太复杂了。

非常感谢

仅使用 do-notation 和条件语句,我找到了以下解决方案:

readUntil :: (String -> Bool) -> IO [String]          
readUntil f = do x <- getLine; 
                 if f x then (return []) else (do xs <- readUntil f
                                                  return (x : xs))

函数首先从prelude中读取一行getLine,然后检查(f x)是否为真。然后 return 只是一个空列表。我们不能只写 ... if f x then [] ...,因为 [] 的类型不是 IO [String],而是 [String]。要使 [] 成为 IO [String] 类型,我们可以使用函数 returnpure 但使用 do-notation 我使用 return 函数,因为它包含在Monad 类型类。 如果 f x 等于 False,那么我们将使用第二个 do-block 一次又一次地递归调用该函数,直到我们得到一个输入,其中 f x == True 因此 return 是空的列表。 do-notation 是必需的,因为 xs 必须具有类型 [String],但 readUntil 具有类型 IO [String]。我们不能对类型为 IO String 的对象使用 :(“缺点”)运算符,因此无法生成我们想要的列表。然后,我们将 x 添加到所有其他输入的列表 xs 中并 return 它。

对于函数 readUntil 的更通用版本,它能够与任何 monad 而不仅仅是 IO Monad 一起工作,请参阅 Will Ness

的评论