【问题标题】:Why this dictionary function is not working为什么这个字典功能不起作用
【发布时间】:2019-10-06 19:50:57
【问题描述】:

我正在尝试使用来自here 的代码创建和使用字典:

import Data.List (lookup)

insert :: Eq a => (a,b) -> [(a,b)] -> [(a,b)]
insert (a,b)  []           = [(a,b)]
insert (a,b) ((c,d):rest) = if a == c
    then (a,b) : rest
    else (c,d) : insert (a,b) rest

dict :: [(String, String)]
dict = [("", "")]

main = do 
    insert ("onekey", "onevalue") dict
    print dict
    print $ lookup "onekey" dict

但我收到以下错误:

$ runghc rndict.hs

rndict.hs:22:1: error:
    • Couldn't match expected type ‘IO t0’ with actual type ‘[()]’
    • In the expression: main
      When checking the type of the IO action ‘main’

rndict.hs:24:9: error:
    • Couldn't match type ‘IO’ with ‘[]’
      Expected type: [()]
        Actual type: IO ()
    • In a stmt of a 'do' block: print dict
      In the expression:
        do { insert ("onekey", "onevalue") dict;
             print dict;
             print $ lookup "onekey" dict }
      In an equation for ‘main’:
          main
            = do { insert ("onekey", "onevalue") dict;
                   print dict;
                   print $ lookup "onekey" dict }

rndict.hs:25:9: error:
    • Couldn't match type ‘IO’ with ‘[]’
      Expected type: [()]
        Actual type: IO ()
    • In a stmt of a 'do' block: print $ lookup "onekey" dict
      In the expression:
        do { insert ("onekey", "onevalue") dict;
             print dict;
             print $ lookup "onekey" dict }
      In an equation for ‘main’:
          main
            = do { insert ("onekey", "onevalue") dict;
                   print dict;
                   print $ lookup "onekey" dict }

有什么问题,在 Haskell 中使用字典的正确方法是什么?

【问题讨论】:

标签: dictionary haskell compiler-errors type-mismatch do-notation


【解决方案1】:

您需要使用let 将新字典绑定到一个名称:

import Data.List (lookup)

insert :: Eq a => (a,b) -> [(a,b)] -> [(a,b)]
insert (a,b)  []           = [(a,b)]
insert (a,b) ((c,d):rest) = if a == c
    then (a,b) : rest
    else (c,d) : insert (a,b) rest

dict :: [(String, String)]
dict = [("", "")]

main = do
    let d = insert ("onekey", "onevalue") dict
    print d
    print $ lookup "onekey" d

您询问有关插入多个元素的问题。为此,您可以使用折叠来编写一个名为insertMany 的函数。您可能应该使用foldl',但我会将其留作练习以找出原因。

import Data.List (lookup)

insert :: Eq a => (a,b) -> [(a,b)] -> [(a,b)]
insert (a,b)  []           = [(a,b)]
insert (a,b) ((c,d):rest) = if a == c
    then (a,b) : rest
    else (c,d) : insert (a,b) rest

insertMany :: Eq a => [(a,b)] -> [(a,b)] -> [(a,b)]
insertMany elements dict =
  foldl (flip insert) dict elements

dict :: [(String, String)]
dict = [("", "")]

main = do
    let d = insert ("onekey", "onevalue") dict
    print d
    print $ lookup "onekey" d
    print $ insertMany [("onekey", "newvalue"), ("anotherkey", "anothervalue")]
      dict

【讨论】:

  • 我可以不使用let dict =...更改原始字典
  • 你不会改变它,而是引入一个隐藏原始名称的名称。
  • 我必须多次重复这个插入过程。我发现它第二次无法正常工作。
  • 请注意,insert 不会发生变异,但每次都会返回一个新字典。如果需要插入很多元素,可以创建一个函数insertMany,使用折叠或递归。
  • 好的。我需要这个作为答案。
猜你喜欢
  • 1970-01-01
  • 2018-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-09
  • 1970-01-01
相关资源
最近更新 更多