Why can't I use IO constructor

后端 未结 3 1171
陌清茗
陌清茗 2021-02-04 05:39

Why can\'t I do this:

import Data.Char

getBool = do
  c <- getChar
  if c == \'t\' 
    then IO True 
    else IO False

instead of using

3条回答
  •  太阳男子
    2021-02-04 06:06

    You can use IO instead of return. But not such easy. And you also need to import some inner modules.

    Let's look at source of Control.Monad:

    instance  Monad IO  where
        {-# INLINE return #-}
        {-# INLINE (>>)   #-}
        {-# INLINE (>>=)  #-}
        m >> k    = m >>= \ _ -> k
        return    = returnIO
        (>>=)     = bindIO
        fail s    = failIO s
    
    returnIO :: a -> IO a
    returnIO x = IO $ \ s -> (# s, x #)
    

    But even to use IO instead of return, you need to import GHC.Types(IO(..)):

    newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
    

    After this, you can write IO $ \ s -> (# s, True #) (IO is a State) instead of return True:

    Solution:

    {-# LANGUAGE UnboxedTuples #-}  -- for unboxed tuples (# a, b #)
    {-# LANGUAGE TupleSections #-}  -- then (,b) == \a -> (a, b)
    import GHC.Types (IO (..))
    import Data.Char
    
    getBool = do
      c <- getChar
      if c == 't' 
        then IO (# , True #)
        else IO (# , False #)
    

提交回复
热议问题