什么“使用函数依赖项组合时无法匹配类型”错误意味着什么?

时间:2012-04-05 20:49:20

标签: haskell types monad-transformers functional-dependencies

我正在为我正在学习的课程编写一个小编译器。所以我开始编写这个monad变换器来处理类型检查,但是得到了一个非常神秘的类型错误。涉及功能依赖的东西,我真的不太清楚。 该程序的一小段摘录可以重现错误:

import Control.Monad.RWS.Lazy
import qualified Data.Map as M
import Control.Applicative

--Placeholders for other data types.
data TypeError = TypeError
data Ident = Ident String
data Type = Type

type Typer a = RWS FunctionTable [TypeError] IdentTable a

type FunctionTable = M.Map Ident Type

type IdentTable = [M.Map Ident Type]

emptyIdents :: IdentTable
emptyIdents = []

getIdent :: Ident -> Typer (Maybe Type)
getIdent id = getIdent' id <$> get

getIdent' :: Ident -> IdentTable -> Maybe Type
getIdent' _ [] = Nothing
getIdent' id (x:xs) =
  case M.lookup id x of
    Just t -> Just t
    Nothing -> getIdent' id xs

putIdent :: Ident -> Type -> Typer ()
putIdent id ty = modify $ \xs -> case xs of
  [] -> [M.singleton id ty]
  (x:xs) -> (M.insert id ty x) : xs

scopeEnter :: Typer ()
scopeEnter = modify $ \ids -> emptyIdents : ids

scopeExit :: Typer ()
scopeExit = modify tail

实际信息:

[1 of 1] Compiling Main             ( ErrorExample.hs, interpreted )

ErrorExample.hs:30:22:
    Couldn't match type `M.Map Ident Type' with `Type'
    When using functional dependencies to combine
      MonadState
        [[M.Map Ident Type]]
        (RWST
           (M.Map Ident Type)
           [TypeError]
           [M.Map Ident Type]
           transformers-0.2.2.0:Data.Functor.Identity.Identity),
        arising from a use of `modify' at ErrorExample.hs:35:18-23
      MonadState
        [M.Map Ident Type]
        (RWST
           (M.Map Ident Type)
           [TypeError]
           [M.Map Ident Type]
           transformers-0.2.2.0:Data.Functor.Identity.Identity),
        arising from a use of `modify' at ErrorExample.hs:30:22-27
    In the expression: modify
    In the expression:
      modify
      $ \ xs
          -> case xs of {
               [] -> [...]
               (x : xs) -> (M.insert id ty x) : xs }

ErrorExample.hs:30:22:
    Couldn't match type `[]' with `M.Map Ident'
    When using functional dependencies to combine
      MonadState
        [[M.Map Ident Type]]
        (RWST
           (M.Map Ident Type)
           [TypeError]
           [M.Map Ident Type]
           transformers-0.2.2.0:Data.Functor.Identity.Identity),
        arising from a use of `modify' at ErrorExample.hs:35:18-23
      MonadState
        [M.Map Ident Type]
        (RWST
           (M.Map Ident Type)
           [TypeError]
           [M.Map Ident Type]
           transformers-0.2.2.0:Data.Functor.Identity.Identity),
        arising from a use of `modify' at ErrorExample.hs:30:22-27
    In the expression: modify
    In the expression:
      modify
      $ \ xs
          -> case xs of {
               [] -> [...]
               (x : xs) -> (M.insert id ty x) : xs }

ErrorExample.hs:35:18:
    Couldn't match type `Type' with `M.Map Ident Type'
    When using functional dependencies to combine
      MonadState s (RWST r w s m),
        arising from the dependency `m -> s'
        in the instance declaration in `Control.Monad.State.Class'
      MonadState
        [[M.Map Ident Type]]
        (RWST
           (M.Map Ident Type)
           [TypeError]
           [M.Map Ident Type]
           transformers-0.2.2.0:Data.Functor.Identity.Identity),
        arising from a use of `modify' at ErrorExample.hs:35:18-23
    In the expression: modify
    In the expression: modify $ \ ids -> emptyIdents : ids

ErrorExample.hs:35:18:
    Couldn't match type `M.Map Ident' with `[]'
    When using functional dependencies to combine
      MonadState s (RWST r w s m),
        arising from the dependency `m -> s'
        in the instance declaration in `Control.Monad.State.Class'
      MonadState
        [[M.Map Ident Type]]
        (RWST
           (M.Map Ident Type)
           [TypeError]
           [M.Map Ident Type]
           transformers-0.2.2.0:Data.Functor.Identity.Identity),
        arising from a use of `modify' at ErrorExample.hs:35:18-23
    In the expression: modify
    In the expression: modify $ \ ids -> emptyIdents : ids
Failed, modules loaded: none.
Leaving GHCi.

1 个答案:

答案 0 :(得分:4)

这是一个非常糟糕的错误消息。原因是由于州内的类型不匹配。您的代码正在尝试混合[M.Map Ident Type]和[[M.Map Ident Type]]。

如果手动将emptyIdents调用内联到scopeEnter,它看起来像这样:

scopeEnter :: Typer ()
scopeEnter = modify $ \ids -> [] : ids

......这对[M.Map Ident Type]没有多大意义。将其与做类型检查的版本进行比较:

scopeEnter :: Typer ()
scopeEnter = modify $ \ids -> M.empty : ids