使用ContT构造器创建新的Monad Cont

时间:2015-03-09 01:39:23

标签: haskell

我开始阅读The Mother of All Monads,并输入了这个例子:

import Control.Monad.Cont

ex1 = do
  a <- return 1
  b <- return 10
  return $ a+b

但是我遇到了编译时错误:

ghci> :l ContMonad.hs 
[1 of 1] Compiling Main             ( ContMonad.hs, interpreted )

ContMonad.hs:4:4:
    No instance for (Monad m0) arising from a do statement
    The type variable ‘m0’ is ambiguous
    Relevant bindings include
      ex1 :: m0 Integer (bound at ContMonad.hs:3:1)
    Note: there are several potential instances:
      instance Monad ((->) r) -- Defined in ‘GHC.Base’
      instance Monad IO -- Defined in ‘GHC.Base’
      instance Monad [] -- Defined in ‘GHC.Base’
      ...plus six others
    In a stmt of a 'do' block: a <- return 1
    In the expression:
      do { a <- return 1;
           b <- return 10;
           return $ a + b }
    In an equation for ‘ex1’:
        ex1
          = do { a <- return 1;
                 b <- return 10;
                 return $ a + b }
Failed, modules loaded: none.

如何让这个简单的例子进行类型检查?

1 个答案:

答案 0 :(得分:11)

问题是ex1作为表达式适用于任何 monad,并且未指定使用的monad。 ex1的类型很可能是ex1 :: (Num b, Monad m) => m b但是,由于dreaded monomorphism restriction,GHC无法推断出这种多态类型,因此结果不明确。

你可以通过给它一个显式的类型签名或禁用单态限制来编译它:

{-# LANGUAGE NoMonomorphismRestriction #-}

在GHCi中使用此功能时,由于extended default rules,它会自动将ex1的值默认为IO Int

*Main> ex1
11

这些规则的存在是为了使ghci可用作计算器并提示执行IO操作。

您还应该尝试与其他一些monad一起看看会发生什么:

*Main> ex1 :: [Int]
[11]
*Main> ex1 :: Maybe Int
Just 11