Haskell中的子串

时间:2011-10-21 01:53:40

标签: list haskell substring

我应该拆分一个字符串并返回在传递的字符之前发生的子字符串,但我们只是启动Haskell,对我来说就像中文一样。我一直搞乱它,但没有运气。 这是我到目前为止所做的:

--spanString returns substring of string s before char c
spanString (c, [s])::(c, [s]) -> []
spanString (c, a:b) =
   let (x, y) = spanString (c, b)
   in
      if a < c then (a:x,y)
      else (x, a:y)

我搞砸了什么?

4 个答案:

答案 0 :(得分:4)

首先,你的类型签名完全搞砸了。它必须不存在或者是spanString :: <some type>形式。即使我们忽略了双冒号之前的(c, [s]),其余的仍然是奇怪的。可以将其视为“将(c, [s])类型的值赋予任何c和s的类型[]的值的函数”(c和s是类型变量)。首先,Haskell中没有类型[]。没有元素类型的列表类型。接下来,我们无法使用任何cs。我们必须能够比较它们,对吗?

实际上,让我们暂时避免使用多态,并准确指定我们想要的类型。我们想要一个字符和一个字符列表,由于某种原因打包成元组:(Char, [Char])。请注意,Char以大写字母开头,这意味着它不是类型变量,而是具体类型。我们的结果类型怎么样?如果您信任问题描述,则需要返回一个字符列表([Char]),但是如果查看代码,它显然会返回列表元组(([Char], [Char]))。好吧,也许第二个列表很有用,让我们暂时离开:

spanString :: (Char, [Char]) -> ([Char], [Char])`

现在您的代码已编译。

但是,在运行时,它会崩溃,但例外情况为Non-exhaustive patterns in function spanString。这是因为当传递的列表为空时,您不处理这种情况。如果你这样做,可以添加像

这样的等式
spanString (_, []) = ([], [])

,你的功能运行良好,但现在让我们来看看它的作用。事实证明,你有一个列表分区功能:它返回给定字符串的所有字符,小于c作为元组的第一个元素,所有其他字符作为第二个元素。对我来说似乎是一个错误(你实现了一个完全不同的功能!)。

答案 1 :(得分:3)

呃,非常多。

首先,您的类型声明是错误的。 Haskell对类型使用大写名称,并且它不像大多数语言那样传递括号中的参数。我们写了

y = sin x

而不是

y = sin (x)

你可能想要像

这样的东西
spanString :: Char -> String -> String

你对spanString的定义在语法上是正确的,但仍然是错误的。这样考虑一下:如果第一个字符不匹配,那么你想要spanString其余的字符串然后返回结果,前面加上第一个字符。如果第一个字符匹配,那么您想要返回“”。

答案 2 :(得分:2)

您的类型定义错误。

   spanString :: Char-> String-> String
   spanString _ [] = []
   spanString c (x:xs) | c==x = []
                       | otherwise = x:spanString c xs

答案 3 :(得分:0)

仅供参考,像这样的实用程序函数几乎总是可以在Prelude或标准库中找到。在这种情况下,takeWhile会有所帮助:

spanString :: (Char, String) -> String
spanString (c, s) = takeWhile (/= c) s

(即,在不等于c时)继续拍摄角色。

在元组中传递参数有点奇怪,但如果这就是所需要的那么就是它。