如何在Haskell的String列表中添加String的字母?

时间:2016-01-25 22:01:49

标签: string list haskell

我正在尝试在String列表中添加String的某些字母。

例如:"Haskell" -> ['a', 's'](仅as

运行后,我收到错误消息“范围内注意:xs”。所以它没有列表(我认为)。将列表转换为新列表(例如mirrorList)没有问题,但是在获得字符串输入后如何“创建”列表?

letterList :: String -> [String]
letterList s = let x = head s in 
                     if x == 'a' || x == 's' then x:xs 
                     else letterList (tail x)

4 个答案:

答案 0 :(得分:6)

在找到准确的问题之前,让我们修复这些类型。您的示例"Haskell" -> ['a', 's']表示此函数的类型为String -> String,而不是String -> [String]。请注意,String只是[Char]的类型别名。

错误消息表示您有一个引用值xs的表达式,但您没有定义任何名为xs的内容。我怀疑你选择x:xs是模式匹配。该模式位于=的左侧,并声明了您可以在右侧引用的xxs。而且由于空列表无法解析为头尾,因此需要一个单独的案例。

我猜测你看到的结果如下:

letterList :: String -> String
letterList []     = []
letterList (x:xs) = if x == 'a' || x == 's' then x:rest else rest
                    where rest = letterList xs

我认为你在这里使用递归只是为了练习,但是为了它的价值,我建议把它写成

letterList :: String -> String
letterList = filter (`elem` "as")

答案 1 :(得分:2)

  •   

    不在范围内:xs

    这就是它所说的内容:没有找到名为xs的变量,但你试图使用它。当你尝试调用一个无法定义的方法时,你也会在Java中遇到同样的错误。

  •   

    将列表转换为新列表(例如mirrorList)没有问题

    这是你在Haskell中永远不需要的东西。如果您有一个列表,您可以随时使用它,无论您喜欢哪种方式。由于引用透明性,它的值和副本之间永远不会有差异。而且我不确定你在这里“转换”是什么意思,但通常可以避免在Haskell中转换任何内容:参数多态通常允许你从一开始就生成正确的类型。

现在关于“我如何创建列表” - 你已经做到了! : 中的cons(prepend)运算符x:xs构造了一个新列表。 ......当然,它基于现有的列表xs。这实际上是生成新列表的唯一方式,因为列表构造函数总是需要一个尾部来预先添加元素。如果您不想/不需要/有任何此类列表,请使用始终可用的空的[]

即使在Haskell中,您有时也需要使用可变数据(通常是ST monad中的数组 - 内部可变,但从外部查看时仍保证引用转发)。在这样的计算中,可能需要复制一个数组,就像它可以用过程语言一样。

答案 2 :(得分:1)

错误消息显示 - 您在右侧使用xs但在使用之前未定义它(即之前没有let语句,之后没有where语句,并且也不在左手边。

除了这个答案

您还有一个问题是您基本上是在实施过滤器,但结果类型是String而不是[String]

letterList :: String -> [String]
letterList [] = []
letterList (x:xs) = if x == 'a' || x == 's'
                      then [x]: letterList xs 
                      else letterList xs
  • 如果您提供空的String
  • ,第一种情况可以防止出错
  • 下一行解构Stringhead = x中的tail = xs,这更加可读和正确(tail x错误,您尝试结束单个字母!)
  • 下一个[x]会转换Char中的单个字母String = [Char]

更优雅/家庭作业

letterList str = [[x] | x <- str, x `elem` "as"]

这被称为列表理解,这将是我将给你思考的下一个“作业”。

letterList str = map (\x -> [x]) $ filter (`elem` "as") str

使用高阶函数(filtermap),这是我给你的第二个任务。

修改

当然,您也可以将类型签名更改为String -> String,如@ChrisMartin所示 - 然后您可以省略[语句中的][x]和省略map (\x -> [x])事。

答案 3 :(得分:-3)

似乎是一个复制粘贴错误:尝试用(尾部x)替换xs ...然后考虑一下情感列表问题......也许你会替换左侧的那一面;-)