我对Haskell很新。我正在尝试编写一个程序,它接受两个值和一个列表,并用第二个值替换列表中第一个值的每个实例。例如。 repOcc 'n' 'i' "pink"
会返回"piik"
。
以下是我的代码:
repOcc :: t -> t -> [t] -> [t]
repOcc x y (z:zs) = if z == x
then z = y
subst x y zs
else subst x y zs
我在编译时收到的错误是:
rev.hs:3 :32: error:
parse error on input '='
Perhaps you need a 'let' in a 'do' block?
e.g. 'let x = 5' instead of 'x = 5'
Failed, modules loaded: none.
答案 0 :(得分:3)
您的计划看起来更像是命令"而Haskell的目标是更多" 声明"。因此,您无法在列表中设置变量z
:一旦构建了列表,您就不能再对其进行更改。因此,您必须构建一个新列表,其中等于x
的元素设置为y
。
接下来,您将使用(==)
功能。该函数在Eq
类型类中定义,因此您需要将Eq t
作为类型约束添加到签名中。
所以现在我们可以开始构建这样的功能了。通常在使用列表时,我们使用递归。递归的基本情况通常是空列表。如果我们遇到空列表,我们应该返回一个空列表,无论x
和y
是什么。所以我们使用下划线作为" 不关心"模式,并使用[]
作为列表模式,并写:
repOcc _ _ [] = []
递归情况是指列表包含h
模式中的头t
和尾(h:t)
。在这种情况下,我们会检查h
是否等于x
。如果是,我们构建一个以y
为首的列表,否则h
仍然是头部。
repOcc x y (h:t) | x == h = y : tl
| otherwise = h : tl
现在问题仍然是结果列表tl
的尾部应该是什么。我们在这里使用递归,因此我们使用repOcc
调用x y t
:
where tl = repOcc x y t
或者把它放在一起:
repOcc :: Eq t => t -> t -> [t] -> [t]
repOcc _ _ [] = []
repOcc x y (h:t) | x == h = y : tl
| otherwise = h : tl
where tl = repOcc x y t
我们可以编写这样的递归函数,但上面实际上是map
函数的一个特例:我们以检查它是否等于x
的方式映射每个字符,如果它是的,我们返回y
,否则我们返回h
。所以我们可以将上面的内容重写为:
repOcc :: Eq t => t -> t -> [t] -> [t]
repOcc x y ls = map (\h -> if h == x then y else h) ls
我们可以通过使用 eta -reduction进一步改进代码:
repOcc :: Eq t => t -> t -> [t] -> [t]
repOcc x y = map (\h -> if h == x then y else h)