1

我写了一个函数f,我在 a 中使用它foldM

foldM (f xs) [] ids
...
f xs acc id = case lookup id xs of
    Just x -> return $ acc ++ [(id, x)]
    Nothing -> throwError $ TypeError "Cannot project nonexisting field"

我为它写的类型签名是:

[(String, Value)] -> [(String, Value)] -> String -> EvalMonad [(String, Value)]

然后我决定删除类型签名,因为函数本身就足够简单且具有描述性。当我使用 hdevtools 获取推断类型时,我得到了

[(t, t)] -> [(t, t)] -> t -> m [(t, t)]

这是什么?我猜 t 与通常的ab您通常看到的不同。元组的第一个和第二个元素不是同一类型(不,SValue 不是 String 的类型同义词),而此签名暗示了该约束。另外,为什么 monad m 没有类约束?我在这里没有使用整个 EvalMonad 堆栈,但m至少应该是MonadError.

4

1 回答 1

2

我使用 ghci 来检查您的代码的推断类型,如下所示:

f typeError xs acc id = case lookup id xs of
    Just x -> return $ acc ++ [(id, x)]
    Nothing -> throwError $ typeError "Cannot project nonexisting field"

(请注意,我将 fixTypeError变成了一个额外的参数typeError,因此我不必对其进行定义)

我得到的类型是:

f :: (Eq t, MonadError e m) =>
     ([Char] -> e) -> [(t, t1)] -> [(t, t1)] -> t -> m [(t, t1)]

所以我不确定为什么你会得到一个带有[(t, t)]或没有约束的类型。t在类型签名中确实与aor相同b;在一个类型中,任何以小写字母开头的标识符都是一个类型变量,在一个类型中多次重复一个这样的标识符表示同一个类型变量。

于 2013-07-10T02:22:01.017 回答