【发布时间】:2013-03-11 14:31:11
【问题描述】:
返回列表列表 ([[a]]) 但不使用空列表 ([]:[a]) 的语法是什么(如果可能的话)? (类似于下面第二个注释的后卫(2),这是不正确的)
这是一个正常工作的函数:
-- Split string on every (shouldSplit == true)
splitWith :: (Char -> Bool) -> [Char] -> [[Char]]
splitWith shouldSplit list = filter (not.null) -- would like to get rid of filter
(imp' shouldSplit list)
where
imp' _ [] = [[]]
imp' shouldSplit (x:xs)
| shouldSplit x = []:imp' shouldSplit xs -- (1) this line is adding empty lists
-- | shouldSplit x = [imp' shouldSplit xs] -- (2) if this would be correct, no filter needed
| otherwise = let (z:zs) = imp' shouldSplit xs in (x:z):zs
这是正确的结果
Prelude> splitWith (== 'a') "miraaaakojajeja234"
["mir","koj","jej","234"]
但是,它必须使用“过滤器”来清理其结果,所以我想摆脱“过滤器”功能。 这是不使用过滤器的结果:
["mir","","","","koj","jej","234"]
如果使用“| shouldSplit x = imp' shouldSplit xs”代替第一个守卫,结果不正确:
["mirkojjej234"]
第一个守卫 (1) 添加空列表,因此(我假设)编译器可以将结果视为列表列表 ([[a]])。
(我对函数的另一种/不同解决方案不感兴趣,只是语法说明。)
.
.
.
回答:
来自 Dave4420 的回答让我找到了答案,但这是一个评论,而不是一个答案,所以我不能接受它作为答案。问题的解决方案是我问错了问题。不是语法问题,而是我的算法问题。
解决空列表问题的另一个/不同解决方案有几个答案,但它们不是我问题的答案。但是,他们扩展了我对如何使用基本 Haskell 语法完成事情的方法的看法,为此我感谢他们。
编辑:
splitWith :: (Char -> Bool) -> String -> [String]
splitWith p = go False
where
go _ [] = [[]]
go lastEmpty (x:xs)
| p x = if lastEmpty then go True xs else []:go True xs
| otherwise = let (z:zs) = go False xs in (x:z):zs
【问题讨论】:
-
谢谢,我知道,但是如果我使用(2),编译器会抱怨发生检查:无法构造无限类型:a0 = [a0] 预期类型:[a0] 实际类型:[ [a0]] 在 imp' 调用的返回类型中 在表达式中:imp' shouldSplit xs 编辑:似乎我删除了原始评论。这是关于使用单元素列表 [a]
-
您似乎认为这是找到正确语法的问题,但这是您算法的结果:当参数连续有4个
as时,您自然会得到3个空结果中的列表。 -
imp' shouldSplit xs和[]:imp' shouldSplit xs的类型都是正确的[[Char]]。他们两个都不工作。[imp' shouldSplit xs]将是[[[Char]]]类型,这当然是不正确的,也不能工作。没有神奇的语法可以将imp' shouldSplit xs转换为一个在没有filter的情况下也可以工作的值,而无需更改算法的其他部分。 -
@dave4420:你让我思考了,所以我用
['x']替换了[],并意识到守卫中的空列表被添加为关闭最后一个单词的最后一个元素,而其他只是一个结果没有任何元素。我现在意识到这不是语法问题,而是算法问题。谢谢! -
@n.m.:
[]:imp' shouldSplit xs不起作用是什么意思?这个工作并产生正确的结果。