我写了一个函数f
,我在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与你常见的a
或b
不同。元组的第一个和第二个元素不是相同的类型(不,SValue不是String的类型同义词),而此签名暗示该约束。另外,为什么monad m没有类约束?我这里没有使用整个EvalMonad堆栈,但m
至少应该是MonadError
的一个实例。
答案 0 :(得分: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"
(请注意,我将固定的TypeError
变为额外的参数typeError
,因此我没有必要对其进行定义。
我得到的类型是:
f :: (Eq t, MonadError e m) =>
([Char] -> e) -> [(t, t1)] -> [(t, t1)] -> t -> m [(t, t1)]
所以我不确定为什么你会得到[(t, t)]
类型的东西,或没有约束。类型签名中的t
确实与a
或b
相同;在类型中,任何以小写字母开头的标识符都是类型变量,单个类型中单个此类标识符的多次重复表示相同的类型变量。