【问题标题】:Create a variable inside a function Haskell在函数 Haskell 中创建一个变量
【发布时间】:2021-11-11 13:42:37
【问题描述】:

我有两个字符串;一个主字符串,另一个是两个字符中的一个(例如“aa”)。

我想看看我的主字符串是否包含第二个字符串并在主字符串中打印它的索引。

我已尝试将主字符串与自身一起压缩,这样我就可以检查彼此之后出现的每个字母组合(例如,“abab”= (a,b) (b,a) (a,b)) .我用 [1..] 压缩这些元组以获得匹配字符串可能开始的正确索引((a,b)0)。然后我用 fst(fst h) 从元组中提取第一个字母,看看它是否与我的辅助字符串的第一个字母匹配。如果它没有找到任何匹配项,它应该在主字符串 (xs) 的其余部分上再次运行。我使用where 将变量h 声明为head(locateZip x:xs)

locate (x:xs) (y:ys) = if fst(fst h) == y && snd(fst h) == ys then snd h else locate xs (y:ys)
                 where h = head(locateZip x:xs)
locateZip xs = zip(zip xs(tail xs)) [0..]

snd h用于打印元组的索引。

它应该返回如下内容:

locate "aabba" "aa" 
0

locate "bbaab" "aa"
2

我知道这可能看起来不寻常,但我还是新手,无法理解我遇到的错误以及哪些有效,哪些无效。

我在h 上收到错误消息:

Couldn't match expected type: ((Char, b2), b3) with actual type: [((b0, b0), b1)]

where 语句是否正确用于此功能?

【问题讨论】:

  • 能否提供一个定位函数的用例?是不是类似于: > locate "abcaad" "aa" 返回一个元组,例如 (3,4),假设字符串位置从零开始?
  • 我现在进行了编辑:)
  • 我只需要它来处理第一个索引。所以在你的例子中它只需要输出 3

标签: haskell


【解决方案1】:

我在您的代码中发现了三个问题。两个是语法问题,一个是逻辑问题。我试图尽可能少地改变。

首先,在where语句中,必须使用()和“:”运算符:

where h = head(locateZip (x:xs))

在您的代码中,Haskell 为 locateZip 函数推断了不同的类型。

其次,在下面的比较中

snd(fst h) == ys

ys 是一个列表,而不是一个字符。这是因为“:”运算符将列表拆分为列表的第一个元素和列表的尾部,就像在函数的开头发生的那样:

locate (x:xs) (y:ys)

现在,逻辑问题。使用 where,只要调用 locate 函数,您就会生成一个 zip 列表。但是,无论何时调用 locateZip 函数,都会重新生成索引。然后,在您最初的想法中,只要找到该对,locate 函数就会输出 0。

还有另一个问题,因为您的定位函数在开始时没有保护来停止递归。好吧,经过一些更改,下面的代码似乎可以按您的预期工作:

locate [] _ = -1
locate phrase pair = locate_aux phrase pair (locateZip phrase)
locate_aux _ _ [] = -1
locate_aux (x:xs) (y1:y2:ys) h = 
    if (fst (fst (head h)) == y1) && (snd (fst (head h)) == y2) then 
        snd (head h) 
    else
        locate_aux xs (y1:y2:ys) (tail h)
locateZip xs = zip(zip xs(tail xs)) [0..]

【讨论】:

  • 所以在您的代码中 h 是 locateZip 短语,这意味着您没有将其作为 where 语句,而是创建了一个帮助函数以将其作为输入启用?由于我的“对”只有两个字母,因此使用 y1:y2:ys 是否与使用 head ys 为 y1 和 last ys 为 y2 相同?
  • 另外,感谢您一步一步地完成它:) 不理解令人沮丧
  • 最后一个问题,我忘了一个词可能有几个实例。如何存储该对的索引并将它们全部打印为列表?例如:“aabbaa”“aa”[0,4]
  • 运算符 ":",当在 "=" 符号(函数签名)之前使用时,会强制对函数调用中传递的参数进行模式匹配。当我们使用“y:ys”时,y 是第一个元素,ys 是列表中没有第一个元素的其余部分。因此,您不能将 ys 与字符进行比较。另一种方法是强制至少两个元素,例如“y1:y2:ys”。由于您的问题仅限于一对,因此在函数调用中使用字符串很方便,但我们必须在函数实现中处理它。更好的选择可能是定义具有两个字符的用户类型并在您的函数中使用它。
  • 关于上一个问题,您可以将 locate 和 locate_aux 更改为返回列表。返回 -1 时,您将返回一个空列表 ([])。对于插入元素,您可以使用递归。当您找到一个实例时(当表达式为 True 时),您将其索引插入到查找其他实例的递归调用中。就是这样。
猜你喜欢
  • 1970-01-01
  • 2011-03-28
  • 1970-01-01
  • 1970-01-01
  • 2018-05-29
  • 2018-03-22
  • 2019-02-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多