我一直在研究Haskell,更具体地说是IO
monad,我想知道如何做到以下几点:
假设我有这个函数签名:
getNumber :: String −> (Int −> Bool) −> IO Int
和本文:
“我的名字是加里,我才21岁”
如果我只想从这句话中读出数字“21”,我将如何在Haskell中完成?
答案 0 :(得分:1)
这可以通过列表处理操作来完成,
import Text.Read
import Data.Char
getNumber :: String -> Maybe Int
getNumber = readMaybe . takeWhile isDigit . dropWhile (not . isDigit)
现在使用它来构建你的功能要容易得多。目前尚不清楚Int -> Bool
的用途,或者,如果您已经有字符串,为什么需要IO
。要获得功能,您可以执行类似
yourFunc :: (Int -> Bool) -> IO Int
yourFunc f = do
r <- fmap getNumber getLine
case r of
Nothing -> putStrLn "Please enter a number" >> yourFunc f
Just x | f x -> return x
| otherwise -> putStrLn "Doesn't satisfy predicate" >> yourFunc f
用法:
> yourFunc even
I am a person
Please enter a number
I am 21
Doesn't satisfy predicate
I am 22
22
但是如果你想进行任何严肃的解析,我会推荐Parsec或Attoparsec,它们都非常易于使用且更加强大。
答案 1 :(得分:1)
这是一个从String
:
import Data.List (unfoldr, tails)
import Data.Maybe (listToMaybe)
readMany :: Read a => String -> [a]
readMany = unfoldr $ listToMaybe . concatMap reads . tails
例如:
> readMany "I like the numbers 7, 11, and 42." :: [Int]
[7,11,42]
您可以轻松地将此专门化为jozefg的函数getNumber
:
justOne :: [a] -> Maybe a
justOne [x] = Just x
justOne _ = Nothing
getNumber :: String -> Maybe Int
getNumber = justOne . readMany
或者你可以稍微宽松一点,并在指定多个时选择第一个数字:
getNumber = listToMaybe . readMany