Haskell Newbie-发生检查:无法构造无限类型:a〜[a]

sod*_*unk 1 haskell

我试图做一个带有3个参数的函数“ tokenize”。main String,应该在自己的String中的字符字符串,以及要从字符串中删除的chars字符串。

tokenize :: String -> String -> String -> [String]
tokenize [] imp remm = []
tokenize str imp remm =   let chr = (head str) in
                          if elem chr imp then ([chr] : (tokenize (tail str) imp remm))
                          else if (elem chr  remm ) then (tokenize (tail str) imp remm)
                          else chr: (tokenize (tail str) imp remm)
Run Code Online (Sandbox Code Playgroud)

我收到此错误消息:

Occurs check: 
cannot construct the infinite type: a ~ [a]
Expected type: [a]
Actual type: [[a]]
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 6

在表达式中,使用两个子表达式:

[chr] : (tokenize (tail str) imp remm))
Run Code Online (Sandbox Code Playgroud)

chr: (tokenize (tail str) imp remm)
Run Code Online (Sandbox Code Playgroud)

两者不能彼此和谐,因为那将意味着[chr]并且chr具有相同的类型,因此是错误。

通常在功能编程中,参数以不同的顺序编写。确实,将其tokenize imp remm strimp重要字符,remm要删除的字符和str要处理的字符串一起编写更有意义。

我们可以通过使用辅助函数来实现功能go。这里go基本上应该考虑四种情况:

  1. 我们到达了列表的末尾,因此返回了一个空列表的单例列表;
  2. 第一个字符是要从输出中消除的东西,我们在字符串的尾部递归;
  3. 该字符很重要,我们产生一个空列表,将字符包装在列表中,然后在尾部递归;和
  4. 如果以上所有内容均不适用,则在递归时将字符放在所检索列表的开头。

我们会过滤出空列表,例如,当其中有两个连续字符时,就会发生这种情况imp

例如:

tokenize :: [Char] -> [Char] -> String -> [String]
tokenize imp remm = filter (not . null) . go
    where go [] = [[]]
          go (x:xs) | elem x remm = go xs
                    | elem x imp = [] : [x] : go xs
                    | otherwise = let (y:ys) = go xs in (x:y) : ys
Run Code Online (Sandbox Code Playgroud)

然后我们得出:

Prelude> tokenize "abc" "def" "defaabyesays"
["a","a","b","ys","a","ys"]
Run Code Online (Sandbox Code Playgroud)

但是,最好是通过separt功能解决单独的问题。例如,第一个具有从中删除字符的功能remm,等等。这使您更容易理解和修正功能。