非详尽模式,Haskell
Non-exhaustive patterns, Haskell
我正在尝试编写函数 tails,它按以下方式将字符串转换为字符串列表:
tails "abc" = ["abc", "bc", "c", ""]
这是我的实现:
tails :: [Char] -> [[Char]]
tails (x:xs)
| length (x:xs) == 0 = [""]
| otherwise = (x:xs) : tails xs
如标题所示,此功能中存在非穷尽模式。不幸的是,我不明白这是怎么回事。
我是 Haskell 的新手...任何帮助将不胜感激!
模式是 non-exhaustive 因为它不能接受 []
。列表具有 []
或 a:as
的形式,其中 a
是前导元素,as
是尾随元素的列表。因此模式 x:xs
仅在列表具有前导元素时才匹配。修复给出:
tails :: [Char] -> [[Char]]
tails xs
| length xs == 0 = [""]
| otherwise = let (_:xs') = xs in xs : tails xs'
然后 xs
接受列表而不考虑其形式。
但由于 length
,这是低效的,并且不适用于无限列表。
这应该完全有效,它直接进行模式数学运算:
tails :: [Char] -> [[Char]]
tails [] = [""]
tails xs@(_:xs') = xs : tails xs'
试试这个怎么样,或者至少从中得到一些逻辑。它运作良好。
它有一个辅助函数,可以将字符串转换为单独字符的列表,例如 "abc" 变为 ["a"、"b"、"c"]。像这样处理它们只是不那么复杂,并且有必要在结果列表中收集不同的字符串。函数集中有两个函数,第三个函数保证使用一个参数调用主函数。主要功能在一条线上,但使用了守卫。
ca = [[c] | c <- "abcdef"]
f (l1,ls) | null ls = l1++[[]] | True = f ( l1 ++ [concat ls], (tail ls))
f ([],ca)
["abcdef","bcdef","cdef","def","ef","f",""]
编辑 2018 年 4 月 4 日
我错了。不必事先将列表参数制成列表。通过不这样做,通过删除 concat 函数并将参数列表从元组更改为单独删除的批次或括号,函数变得更简单。
fs l1 ls = if null ls then l1++[""] else fs (l1++[ls]) (tail ls)
它的调用方式也不同。
fs[]"Hello!"
这本身就产生了正确的结果。
Edit/add 2018 年 4 月 11 日
当 Haskell 将输入拆分为头部和尾部且 (x:xs)
可以使用时,不断重复出现(没有双关语)的是对 tail
的依赖。这是一个基本的递归函数,仅对头和尾使用 (x:xs)
。我生成输入列表的所有尾部,包括 null。
t [] = [""]; t (x:xs) = [x:xs] ++ t xs
还有一个将列表作为唯一参数。
t ls = [drop n ls|n<-[0..length ls - 1]]
我正在尝试编写函数 tails,它按以下方式将字符串转换为字符串列表:
tails "abc" = ["abc", "bc", "c", ""]
这是我的实现:
tails :: [Char] -> [[Char]]
tails (x:xs)
| length (x:xs) == 0 = [""]
| otherwise = (x:xs) : tails xs
如标题所示,此功能中存在非穷尽模式。不幸的是,我不明白这是怎么回事。
我是 Haskell 的新手...任何帮助将不胜感激!
模式是 non-exhaustive 因为它不能接受 []
。列表具有 []
或 a:as
的形式,其中 a
是前导元素,as
是尾随元素的列表。因此模式 x:xs
仅在列表具有前导元素时才匹配。修复给出:
tails :: [Char] -> [[Char]]
tails xs
| length xs == 0 = [""]
| otherwise = let (_:xs') = xs in xs : tails xs'
然后 xs
接受列表而不考虑其形式。
但由于 length
,这是低效的,并且不适用于无限列表。
这应该完全有效,它直接进行模式数学运算:
tails :: [Char] -> [[Char]]
tails [] = [""]
tails xs@(_:xs') = xs : tails xs'
试试这个怎么样,或者至少从中得到一些逻辑。它运作良好。 它有一个辅助函数,可以将字符串转换为单独字符的列表,例如 "abc" 变为 ["a"、"b"、"c"]。像这样处理它们只是不那么复杂,并且有必要在结果列表中收集不同的字符串。函数集中有两个函数,第三个函数保证使用一个参数调用主函数。主要功能在一条线上,但使用了守卫。
ca = [[c] | c <- "abcdef"]
f (l1,ls) | null ls = l1++[[]] | True = f ( l1 ++ [concat ls], (tail ls))
f ([],ca)
["abcdef","bcdef","cdef","def","ef","f",""]
编辑 2018 年 4 月 4 日 我错了。不必事先将列表参数制成列表。通过不这样做,通过删除 concat 函数并将参数列表从元组更改为单独删除的批次或括号,函数变得更简单。
fs l1 ls = if null ls then l1++[""] else fs (l1++[ls]) (tail ls)
它的调用方式也不同。
fs[]"Hello!"
这本身就产生了正确的结果。
Edit/add 2018 年 4 月 11 日
当 Haskell 将输入拆分为头部和尾部且 (x:xs)
可以使用时,不断重复出现(没有双关语)的是对 tail
的依赖。这是一个基本的递归函数,仅对头和尾使用 (x:xs)
。我生成输入列表的所有尾部,包括 null。
t [] = [""]; t (x:xs) = [x:xs] ++ t xs
还有一个将列表作为唯一参数。
t ls = [drop n ls|n<-[0..length ls - 1]]