由于模式变量而推断出的无限类型
infinite type inferred due to pattern variable
使用命名整个 case 表达式的模式变量会导致编译正确与错误 "An infinite type was inferred for an expression" 之间的区别。以下编译正确:
m = case Left "anything" of
e@(Left err) -> Left err
(Right f) -> case lookup "key" f of
Nothing -> Left "something else"
(Just x) -> Right x
但是,如果我们使用模式变量 e(用 e 代替 "Left err",功能等效),编译器会标记一个错误:
m = case Left "anything" of
e@(Left err) -> e
(Right f) -> case lookup "key" f of
Nothing -> Left "something else"
(Just x) -> Right x
"An infinite type was inferred for an expression: StrMap t1 while trying to match type t1 with type StrMap t1 while checking that expression case ((lookup "键") f) ...
我知道将 StrMap t1 与 t1 匹配是有问题的。我不明白为什么会这样。此外,在我的原始代码中,消息根本没有引用无限类型。以下是相关摘录:
retrieveDomeinResourceDefinition :: forall e.
ResourceId
-> Namespace
-> (AsyncDomeinFile e (Either String PropDefs))
retrieveDomeinResourceDefinition id ns = do
df <- retrieveDomeinFile (namespaceToDomeinFileName ns)
case df of
e@(Left err) -> pure $ e
(Right f) -> case lookup id f of
Nothing -> pure $ Left ("retrieveDomeinResourceDefinition: cannot find definition of " <> id <> " in DomeinFile for " <> ns)
(Just propDefs) -> pure (Right propDefs)
retrieveDomeinFile :: forall e. Namespace -> AsyncDomeinFile e (Either String DomeinFile)
newtype PropDefs = PropDefs (StrMap Json)
现在编译器告诉我:"Could not match type: PropDefs with type StrMap PropDefs..." 编译器似乎没有注意到查找表达式。事实上,当我用 "pure (Right f)" 替换 "pure (Right propDefs)" 时,错误消失了(另一个出现在绑定 df 的行上,我理解)。
现在我写这篇文章,我注意到 'trying to match type t1 with type StrMap t1' 和 'could not match type: PropDefs with StrMap PropDefs' 之间的相似性。不过,我不明白为什么使用 e 会引入这个问题。
以这种方式使用模式匹配的值在功能上可能是等效的,但类型不是 - 类型系统没有证据表明 Right
的类型变量可以被忽略。
使用第二个示例中的类型 - 当您模式匹配 e@(Left err)
时,e
的类型将为 Either String DomeinFile
- 但您需要 Either String PropDefs
。模式匹配没有 "free up" 右边的类型变量,这就是为什么你必须重新构造 Left
的错误。
使用命名整个 case 表达式的模式变量会导致编译正确与错误 "An infinite type was inferred for an expression" 之间的区别。以下编译正确:
m = case Left "anything" of
e@(Left err) -> Left err
(Right f) -> case lookup "key" f of
Nothing -> Left "something else"
(Just x) -> Right x
但是,如果我们使用模式变量 e(用 e 代替 "Left err",功能等效),编译器会标记一个错误:
m = case Left "anything" of
e@(Left err) -> e
(Right f) -> case lookup "key" f of
Nothing -> Left "something else"
(Just x) -> Right x
"An infinite type was inferred for an expression: StrMap t1 while trying to match type t1 with type StrMap t1 while checking that expression case ((lookup "键") f) ...
我知道将 StrMap t1 与 t1 匹配是有问题的。我不明白为什么会这样。此外,在我的原始代码中,消息根本没有引用无限类型。以下是相关摘录:
retrieveDomeinResourceDefinition :: forall e.
ResourceId
-> Namespace
-> (AsyncDomeinFile e (Either String PropDefs))
retrieveDomeinResourceDefinition id ns = do
df <- retrieveDomeinFile (namespaceToDomeinFileName ns)
case df of
e@(Left err) -> pure $ e
(Right f) -> case lookup id f of
Nothing -> pure $ Left ("retrieveDomeinResourceDefinition: cannot find definition of " <> id <> " in DomeinFile for " <> ns)
(Just propDefs) -> pure (Right propDefs)
retrieveDomeinFile :: forall e. Namespace -> AsyncDomeinFile e (Either String DomeinFile)
newtype PropDefs = PropDefs (StrMap Json)
现在编译器告诉我:"Could not match type: PropDefs with type StrMap PropDefs..." 编译器似乎没有注意到查找表达式。事实上,当我用 "pure (Right f)" 替换 "pure (Right propDefs)" 时,错误消失了(另一个出现在绑定 df 的行上,我理解)。
现在我写这篇文章,我注意到 'trying to match type t1 with type StrMap t1' 和 'could not match type: PropDefs with StrMap PropDefs' 之间的相似性。不过,我不明白为什么使用 e 会引入这个问题。
以这种方式使用模式匹配的值在功能上可能是等效的,但类型不是 - 类型系统没有证据表明 Right
的类型变量可以被忽略。
使用第二个示例中的类型 - 当您模式匹配 e@(Left err)
时,e
的类型将为 Either String DomeinFile
- 但您需要 Either String PropDefs
。模式匹配没有 "free up" 右边的类型变量,这就是为什么你必须重新构造 Left
的错误。