代码之家  ›  专栏  ›  技术社区  ›  lo tolmencre

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

  •  0
  • lo tolmencre  · 技术社区  · 8 年前

    我要将我编写的trie-datat类型转换为 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.
    

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

    在这种情况下,这个错误意味着什么,是什么导致的?

    1 回复  |  直到 8 年前
        1
  •  4
  •   Fyodor Soikin    8 年前

    在简单的haskell 2010中,约束只能应用于类型变量,例如 a b 或者别的什么,但不是更复杂的。

    法律: Show a => a -> String

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

    在这个例子中, Show (Maybe a) 约束是非法的,因为 Maybe a 不是类型变量。 是类型变量,但 也许是一个 不是。

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

    由于没有合理的技术理由不允许这样的约束,除了更难实现外,一个名为 FlexibleContexts 介绍(见 docs )这使得这些限制合法化。这就是编译器告诉你的。你可以打开这个扩展,它没有任何缺点。