了解“约束中的非类型变量参数”

时间:2018-09-04 00:12:00

标签: haskell constraints typeerror

我想将我编写的trie datat类型转换为Data.Tree.Tree

我的特里类型如下:

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.

据我所知,我不理解该错误消息以及在搜索该错误时发现的其他问题确实无法转移到我的代码中。

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

1 个答案:

答案 0 :(得分:4)

在普通的Haskell 2010中,约束只能应用于类型变量,例如ab或其他任何类型,而不能应用于更复杂的任何类型。

法律:Show a => a -> String

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

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

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

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