Haskell代码不会编译

时间:2014-04-12 15:29:56

标签: haskell compiler-errors

我正在努力学习Haskell,所以我想我会潜入并尝试一个monad。请参阅下面的我对Calc的实现。这类似于State monad,除了state始终是用于缓存结果的Map。每个Calc都有自己的GUID(尚未实现),用作从地图中检索缓存值的键。

import qualified Data.Map as Map
import Control.Monad
import Data.Dynamic

type CalcId = Int

type Ctx = Map.Map CalcId Dynamic

data Calc a = Calc { eval :: Ctx -> (a, Ctx),
                 guid :: CalcId }

instance Monad Calc where
    (>>=) :: Calc a -> (a -> Calc b) -> Calc b
    c1 >>= f = Calc {eval=c2Eval, guid=c2Id}
        where c2Id = 1 -- need a way of generating a GUID. add later.
              c2Eval = \ctx -> 
                    case (Map.lookup c2Id ctx >>= fromDynamic) :: Maybe b of
                        Just c2Val -> 
                            (c2Val, ctx)
                        Nothing ->
                            let (c1Val, ctx') = eval c1 ctx
                                c2 = f c1Val
                                (c2Val', _) = eval c2 ctx'
                                ctx'' = Map.insert c2Id (toDyn c2Val') ctx'
                            in (c2Val', ctx'')

此代码可能存在许多问题。但是现在我真的很想让它编译。编译器错误如下;

No instance for (Typeable b1) arising from a use of `fromDynamic'
Possible fix:
  add (Typeable b1) to the context of
    an expression type signature: Maybe b1
    or the type signature for >>= :: Calc a -> (a -> Calc b) -> Calc b
In the second argument of `(>>=)', namely `fromDynamic'
In the expression: (Map.lookup c2Id ctx >>= fromDynamic) :: Maybe b
In the expression:
  case (Map.lookup c2Id ctx >>= fromDynamic) :: Maybe b of {
    Just c2Val -> (c2Val, ctx)
    Nothing
      -> let
           (c1Val, ctx') = ...
           ....
         in (c2Val', ctx'') }

No instance for (Typeable b) arising from a use of `toDyn'
Possible fix:
  add (Typeable b) to the context of
    the type signature for >>= :: Calc a -> (a -> Calc b) -> Calc b
In the second argument of `Map.insert', namely `(toDyn c2Val')'
In the expression: Map.insert c2Id (toDyn c2Val') ctx'
In an equation for ctx'':
    ctx'' = Map.insert c2Id (toDyn c2Val') ctx'

1 个答案:

答案 0 :(得分:5)

问题在于,对于动态值,事物需要成为可键入类的成员。你的下一个问题是你的monad只能用于打字。你的第三个问题是,你不能把它变成monad,因为monads必须能够包含任何东西。看看restricted monads