如何在 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

这在两个地方中断:

  1. main 中,putStrLn 是类型 IO DoublegetDouble 是类型 ThrowsError Double.

  2. getDouble 中,getLine 是类型 IO DoubleparseString returns IO Double.

本质上,我希望能够从 IO monad 中提取值,对其应用计算,然后将其放回适当的 monad 中。但是,绑定函数似乎期望输入和输出使用相同的 monad 类型,所以我想做的是行不通的。

怎么解决的?

你不需要任何变形金刚。 parseString 是一个纯函数,所以要将它应用到你使用 fmap(又名 (<$>))的 monadic 动作,而不是你使用的 (>>=)

getDouble :: IO (ThrowsError Double)
getDouble = parseString <$> getLine

如果 parseString 返回 IO something,您将使用 (>>=)