首页 > 解决方案 > 理解“约束中的非类型变量参数”

问题描述

我想将我写的 trie 数据类型转换为Data.Tree.Tree

我的 trie 类型如下所示:

import qualified Data.Map as DM

data Trie a = Node {
    label :: a,
    edges :: DM.Map a (Trie a),
    isFinal :: Bool
}

现在我写了这个函数进行转换:

import qualified Data.Tree as DT

toDataTree :: (Eq a, Eq (Trie a)) => Trie a -> DT.Tree a
toDataTree (Node label edges isFinal)
    | edges == DM.empty = DT.Node label (map toDataTree (DM.elems edges))
    | otherwise = DT.Node label []

但它不编译。我正进入(状态

    • Non type-variable argument in the constraint: Eq (Trie a)
      (Use FlexibleContexts to permit this)
    • In the type signature:
        toDataTree :: (Eq a, Eq (Trie a)) => Trie a -> DT.Tree a
   |
19 | toDataTree :: (Eq a, Eq (Trie a)) => Trie a -> DT.Tree a
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Failed, no modules loaded.

据我所知,我不明白该错误消息和我在谷歌搜索错误时发现的其他问题并不能真正转移到我的代码中。

在这种情况下,该错误是什么意思,是什么原因造成的?

标签: haskellconstraintstypeerror

解决方案


在普通的 Haskell 2010 中,约束只能应用于类型变量,比如aorb或其他,但不能应用于更复杂的东西。

合法的:Show a => a -> String

非法的:Show (Maybe a) => a -> String

在此示例中,Show (Maybe a)约束是非法的,因为Maybe a它不是类型变量。a是一个类型变量,但Maybe a不是。

在您的代码中,编译器抱怨这Trie a不是约束中的类型变量Eq (Trie a)

由于不允许这样的约束没有合理的技术理由,除了它更难实现之外,FlexibleContexts引入了一个名为的扩展(参见docs),使这样的约束合法。这就是编译器告诉你的。您可以打开此扩展程序,它没有任何缺点。


推荐阅读