如何在 Haskell 中使用来自不同类型 monad 的值
How to use value from different type monad in Haskell
老实说,我觉得这一定是在某个地方被骗了,但我找不到it even searching .
假设我有以下代码来简单地从用户那里读取一个双精度值并将其回显:
import qualified Control.Monad.Except as E
import Text.Read(readMaybe)
data Error = ParseError String
| Default String deriving (Show)
type ThrowsError = Either Error
main = do
putStrLn "Enter your number: "
val <- getDouble
print val
parseString :: String -> ThrowsError Double
parseString val = maybe (E.throwError $ ParseError val) return
(readMaybe val :: Maybe Double)
getDouble :: ThrowsError Double
getDouble = getLine >>= parseString
这在两个地方中断:
在 main
中,putStrLn
是类型 IO Double
但 getDouble
是类型 ThrowsError Double
.
在 getDouble
中,getLine
是类型 IO Double
但 parseString
returns IO Double
.
本质上,我希望能够从 IO
monad 中提取值,对其应用计算,然后将其放回适当的 monad 中。但是,绑定函数似乎期望输入和输出使用相同的 monad 类型,所以我想做的是行不通的。
怎么解决的?
你不需要任何变形金刚。 parseString
是一个纯函数,所以要将它应用到你使用 fmap
(又名 (<$>)
)的 monadic 动作,而不是你使用的 (>>=)
。
getDouble :: IO (ThrowsError Double)
getDouble = parseString <$> getLine
如果 parseString
返回 IO something
,您将使用 (>>=)
。
老实说,我觉得这一定是在某个地方被骗了,但我找不到it even
假设我有以下代码来简单地从用户那里读取一个双精度值并将其回显:
import qualified Control.Monad.Except as E
import Text.Read(readMaybe)
data Error = ParseError String
| Default String deriving (Show)
type ThrowsError = Either Error
main = do
putStrLn "Enter your number: "
val <- getDouble
print val
parseString :: String -> ThrowsError Double
parseString val = maybe (E.throwError $ ParseError val) return
(readMaybe val :: Maybe Double)
getDouble :: ThrowsError Double
getDouble = getLine >>= parseString
这在两个地方中断:
在
main
中,putStrLn
是类型IO Double
但getDouble
是类型ThrowsError Double
.在
getDouble
中,getLine
是类型IO Double
但parseString
returnsIO Double
.
本质上,我希望能够从 IO
monad 中提取值,对其应用计算,然后将其放回适当的 monad 中。但是,绑定函数似乎期望输入和输出使用相同的 monad 类型,所以我想做的是行不通的。
怎么解决的?
你不需要任何变形金刚。 parseString
是一个纯函数,所以要将它应用到你使用 fmap
(又名 (<$>)
)的 monadic 动作,而不是你使用的 (>>=)
。
getDouble :: IO (ThrowsError Double)
getDouble = parseString <$> getLine
如果 parseString
返回 IO something
,您将使用 (>>=)
。