Haskell 从 IO 域获取值
Haskell get values from IO domain
读完 Haskell 书后,我有点困惑(或者我只是忘记了)如何从 IO 域中获取一个值,然后进入 'Haskell world' 来解析它,就像这样:
fGetSeq = do
input <- sequence [getLine, getLine, getLine]
fTest input
mapM_ print input
fTest = map (read :: String -> Int)
显然编译器会报错。 Couldn't match [] with IO
。在 'worlds' 之间传递值是否有简单的经验法则,或者省略 typesigs 只是我的错?
关于 do
符号的事情是,其中的每个 monadic 动作值(那些在 <-
s 右边的,或者在他们自己的行上的)必须属于 the相同 单子。这是
do {
x <- ma ; -- ma :: m a x :: a
y <- mb ; -- mb :: m b y :: b ( with the same m! )
return (foo x y) -- foo x y :: c return (foo x y) :: m c
} -- :: m c
现在,由于 sequence [getLine, getLine, getLine] :: IO [String]
,这意味着您的 do
块属于 IO
。
但是当你得到这些值时,你可以单独对待这些值:
fGetSeq :: IO ()
fGetSeq = do
inputs <- sequence [getLine, getLine, getLine] -- inputs :: [String]
let vals = fTest inputs
mapM_ print vals
fTest :: [String] -> [Int]
fTest = map (read :: String -> Int)
-- or just
fGetSeq1 = do
inputs <- sequence [getLine, getLine, getLine]
mapM_ print ( fTest inputs )
-- or
fGetSeq2 = do { vals <- fTest <$> sequence [getLine, getLine, getLine] ;
mapM_ print vals } -- vals :: [Int]
-- or even (with redundant parens for clarity)
fGetSeq3 = mapM_ print =<< ( fTest <$> sequence [getLine, getLine, getLine] )
-- = mapM_ print . fTest =<< sequence [getLine, getLine, getLine]
Monad 的本质是在潜在不纯的 'effectful' 计算之间分层纯 'Haskell world' 计算。
所以我们已经在 Haskell 的纯净世界中,在 <-
的左侧。同样,inputs :: [String]
。纯粹的价值。
get a value from the IO domain, into the 'Haskell world'
您使用绑定运算符:(>>=) :: Monad m => m a -> (a -> m b) -> m b
.
如果 m = IO
看起来像:(>>=) :: IO a -> (a -> IO b) -> IO b
.
如您所见,类型为 a -> IO b
的函数解决了没有 IO
的 a
。
因此在 IO monad 中给定一个值,例如getLine :: IO String
:
getInt :: IO Int
getInt = getLine >>= (\s -> return (read s))
此处,s :: String
、read :: String -> Int
和return :: Int -> IO Int
。
您可以使用 do-block 重写它:
getInt :: IO Int
getInt = do
s <- getLine
return (read s)
或使用标准库函数来完成此操作:
getInt :: IO Int
getInt = readLn
对于您的示例,您可以使用 let-binding 立即修复它:
foo :: IO ()
foo = do
input <- sequence [getLine, getLine, getLine]
let ints = bar input
mapM_ print ints
bar :: [String] -> [Int]
bar = map read
或者您可以重组它以使用上面定义的 getInt
:
foo :: IO ()
foo = sequence [getInt, getInt, getInt] >>= mapM_ print
读完 Haskell 书后,我有点困惑(或者我只是忘记了)如何从 IO 域中获取一个值,然后进入 'Haskell world' 来解析它,就像这样:
fGetSeq = do
input <- sequence [getLine, getLine, getLine]
fTest input
mapM_ print input
fTest = map (read :: String -> Int)
显然编译器会报错。 Couldn't match [] with IO
。在 'worlds' 之间传递值是否有简单的经验法则,或者省略 typesigs 只是我的错?
关于 do
符号的事情是,其中的每个 monadic 动作值(那些在 <-
s 右边的,或者在他们自己的行上的)必须属于 the相同 单子。这是
do {
x <- ma ; -- ma :: m a x :: a
y <- mb ; -- mb :: m b y :: b ( with the same m! )
return (foo x y) -- foo x y :: c return (foo x y) :: m c
} -- :: m c
现在,由于 sequence [getLine, getLine, getLine] :: IO [String]
,这意味着您的 do
块属于 IO
。
但是当你得到这些值时,你可以单独对待这些值:
fGetSeq :: IO ()
fGetSeq = do
inputs <- sequence [getLine, getLine, getLine] -- inputs :: [String]
let vals = fTest inputs
mapM_ print vals
fTest :: [String] -> [Int]
fTest = map (read :: String -> Int)
-- or just
fGetSeq1 = do
inputs <- sequence [getLine, getLine, getLine]
mapM_ print ( fTest inputs )
-- or
fGetSeq2 = do { vals <- fTest <$> sequence [getLine, getLine, getLine] ;
mapM_ print vals } -- vals :: [Int]
-- or even (with redundant parens for clarity)
fGetSeq3 = mapM_ print =<< ( fTest <$> sequence [getLine, getLine, getLine] )
-- = mapM_ print . fTest =<< sequence [getLine, getLine, getLine]
Monad 的本质是在潜在不纯的 'effectful' 计算之间分层纯 'Haskell world' 计算。
所以我们已经在 Haskell 的纯净世界中,在 <-
的左侧。同样,inputs :: [String]
。纯粹的价值。
get a value from the IO domain, into the 'Haskell world'
您使用绑定运算符:(>>=) :: Monad m => m a -> (a -> m b) -> m b
.
如果 m = IO
看起来像:(>>=) :: IO a -> (a -> IO b) -> IO b
.
如您所见,类型为 a -> IO b
的函数解决了没有 IO
的 a
。
因此在 IO monad 中给定一个值,例如getLine :: IO String
:
getInt :: IO Int
getInt = getLine >>= (\s -> return (read s))
此处,s :: String
、read :: String -> Int
和return :: Int -> IO Int
。
您可以使用 do-block 重写它:
getInt :: IO Int
getInt = do
s <- getLine
return (read s)
或使用标准库函数来完成此操作:
getInt :: IO Int
getInt = readLn
对于您的示例,您可以使用 let-binding 立即修复它:
foo :: IO ()
foo = do
input <- sequence [getLine, getLine, getLine]
let ints = bar input
mapM_ print ints
bar :: [String] -> [Int]
bar = map read
或者您可以重组它以使用上面定义的 getInt
:
foo :: IO ()
foo = sequence [getInt, getInt, getInt] >>= mapM_ print