用字符串元组列表替换字符串

时间:2019-10-13 21:03:37

标签: haskell

我想编写一个名为trained的函数,该函数具有字符串替换功能和单词对列表(字符串的两元组)。

我尝试使用map和lambda函数,但仍然遇到一些错误。在这个问题上的任何帮助将不胜感激!

函数train应该具有以下类型的签名:train :: Eq a => (a -> t) -> [(a, t)] -> a -> t

这是一些错误:

  

无法匹配预期的类型[Char] -> b'
  实际类型为[[Char] -> [Char]]

这是我的代码:

extend repl old new = \str -> if (str == old) then new 
                              else if (str == new) then old 
                              else (repl str)

train fn lst =  map (\(a,b) -> extend fn a b) lst

函数 train 应该如下所示:

In: let improved = train (\s->s) [("kittens","puppies"),
                      ("tea","coffee"),("Java","Haskell")]

In: map improved ["my","favorite","things","are",
                      "kittens","Java","tea","and","rainbows"]

Out: ["my","favorite","things","are","puppies","Haskell","coffee","and","rainbows"]

1 个答案:

答案 0 :(得分:4)

您正试图调用map improved,但是map的第一个参数必须是一个函数,并且:t improved向您显示improved实际上是一个列表功能:improved :: [[Char] -> [Char]]。问题在于train返回的是函数列表,而不是单个组合函数。要解决此问题,请将map (\(a,b) -> extend fn a b)更改为foldr (\(a,b) f -> extend f a b) fn

此外,您的代码有点单调和复杂。这是我的写法:

extend :: Eq a => (a, a) -> (a -> a) -> a -> a
extend (old, new) repl str
  | str == old = new
  | str == new = old
  | otherwise = repl str

train :: Eq a => (a -> a) -> [(a, a)] -> a -> a
train = foldr extend

improved :: String -> String
improved = train id [("kittens","puppies"),("tea","coffee"),("Java","Haskell")]

现在,您已对问题进行了编辑,以包括必需的类型签名,您需要进行以下更改:extend仅可以单向进行替换(即,无法测试str == new,并且将其替换为old)。在这之后,它看起来会很惯用:

extend :: Eq a => (a, t) -> (a -> t) -> a -> t
extend (old, new) repl str
  | str == old = new
  | otherwise = repl str

train :: Eq a => (a -> t) -> [(a, t)] -> a -> t
train = foldr extend

improved :: String -> String
improved = train id [("kittens","puppies"),("tea","coffee"),("Java","Haskell")]
相关问题