我想编写一个名为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"]
答案 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")]