Haskell - 使用IntMap和数据类型键入错误

时间:2018-02-13 05:39:49

标签: haskell trie custom-data-type

我们使用IntMaps在Haskell中实现Tries。但是,我似乎无法想象出IntMaps。

以下是我所拥有的:

charMapLookup :: Char -> IntMap a -> Maybe a
charMapLookup c dict = IntMap.lookup (ord c) dict

charMapInsert :: Char -> a -> IntMap a -> IntMap a
charMapInsert c v dict = IntMap.insert (ord c) v dict

-- Question 1.
data Trie a = TrieOf (Maybe a) (IntMap (Trie a))
    deriving Show

trieLookup :: [Char] -> Trie a -> Maybe a
-- My code
trieLookup [] (TrieOf a t) = a
trieLookup (x:xs) (TrieOf _ t) = trieLookup xs (charMapLookup x t)

trieInsert :: [Char] -> a -> Trie a -> Trie a
trieInsert [] a (TrieOf c t)= TrieOf c t
trieInsert (x:xs) a (TrieOf c t) | isNothing (charMapLookup x t) = trieInsert xs a (charMapInsert x Nothing t)
                                 | trieInsert xs a (charMapLookup x t)

这似乎对我有意义,因为如果字符串中没有任何内容,则返回节点的值,否则在相关子树中搜索字符串的尾部,并且类似于插入但是,当我尝试运行它时:

 Couldn't match expected type ‘Trie a’
                    with actual type ‘Maybe (Trie a)’
        Relevant bindings include
          t :: IntMap (Trie a)
          trieLookup :: [Char] -> Trie a -> Maybe a 
        In the second argument of ‘trieLookup’, namely
          ‘(charMapLookup x t)’
        In the expression: trieLookup xs (charMapLookup x t)
    Failed, modules loaded: none.   

Couldn't match expected type ‘Trie a’
                with actual type ‘IntMap (Maybe a0)’
    Relevant bindings include
      t :: IntMap (Trie a) 
      c :: Maybe a 
      a :: a 
      trieInsert :: [Char] -> a -> Trie a -> Trie a
    In the third argument of ‘trieInsert’, namely
      ‘(charMapInsert x Nothing t)’
    In the expression: trieInsert xs a (charMapInsert x Nothing t)

Couldn't match type ‘Trie a’ with ‘Maybe a0’
    Expected type: IntMap (Maybe a0)
      Actual type: IntMap (Trie a)
    Relevant bindings include
      t :: IntMap (Trie a) 
      c :: Maybe a 
      a :: a
      trieInsert :: [Char] -> a -> Trie a -> Trie a
    In the third argument of ‘charMapInsert’, namely ‘t’
    In the third argument of ‘trieInsert’, namely
      ‘(charMapInsert x Nothing t)’ 

我不确定如何修复错误,我知道它说类型不匹配,但t应该是Tries的IntMap(对吧?)所以我我不知道如何处理这个问题。我花了很长时间试图解决这个问题,任何可以解决问题的代码都会受到极大的赞赏。谢谢!

1 个答案:

答案 0 :(得分:2)

构造第一条错误消息。它发生在trieLookup中,当您获取对应于第一个符号的分支并继续查找密钥的其余部分时。问题是,这个分支不是Trie a而是Maybe (Trie a)(第一个字符可以在根中取消映射)。要继续查找,您需要将其平面映射到可能不合适的分支:

trieLookup (x:xs) (TrieOf _ t) = (charMapLookup x t) >>= trieLookup xs

(或使用case代替>>=,这将处理Nothing的{​​{1}}和Just branch可能结果。

请注意,除了类型错配之外,您的代码还包含更多错误,在编译器输出中未列出:

  1. 在trieInsert中,实际上并不存储映射值:
  2. charMapLookup

    这场比赛的RHS与原来的trie相同,没有变化。

    1. trieInsert中的else子句实际应该是:
    2. trieInsert (x:xs) a (TrieOf c t) | isNothing (charMapLookup x t) = trieInsert xs a (charMapInsert x Nothing t)
                                       | otherwise = trieInsert xs a (charMapLookup x t)