【问题标题】:How to add letters of a String in a String list in Haskell?如何在 Haskell 的字符串列表中添加字符串的字母?
【发布时间】:2016-05-02 09:23:28
【问题描述】:

我正在尝试在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)

【问题讨论】:

  • 什么是mirrorList
  • mirror :: [a] -> [a] mirror [] = [] mirror (x:xs) = [x] ++ mirror xs ++ [x]

标签: string list haskell


【解决方案1】:

在回答您的确切问题之前,让我们先修正一下类型。您的示例"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")

【讨论】:

  • 谢谢你,克里斯!你帮了我很多,尤其是在这部分:where rest = (letterList xs)。我也试过String -> [Char],它也有效。 letterList x = let s = head x in if s == 'a' || s == 's' then s:rest else letterList rest where rest = (letterList (tail x))
【解决方案2】:

错误消息说-您在右侧使用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,第一种情况可以防止错误!
  • 下一行解构head = xtail = xs 中的String,这样更易​​读也更正确(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 -&gt; String,如@ChrisMartin 所示 - 然后您可以在[x] 语句中省略[,],并分别省略map (\x -&gt; [x]) 事物。

【讨论】:

    【解决方案3】:
    • 不在范围内:xs

      这就是它所说的:没有找到名为xs 的变量,但您尝试使用它。在尝试调用未定义的方法时,这与您在 Java 中遇到的错误大致相同。

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

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

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


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

    【讨论】:

    • 感谢您的回答。我没有很好地表达自己。我的错。我不会将列表转换为新列表,我只是镜像相同的列表。 mirror :: [a] -&gt; [a] mirror [] = [] mirror (x:xs) = [x] ++ mirror xs ++ [x]
    • 啊哈。请注意,您可以简单地将其定义为 mirror xs = xs ++ reverse xs
    【解决方案4】:

    似乎是复制粘贴错误:尝试将 xs 替换为 (tail x) ...然后考虑 emoty-list 问题...也许你也会替换左侧 ;-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-09
      • 1970-01-01
      • 2015-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-27
      相关资源
      最近更新 更多