2017-08-27 203 views
-2

我是Haskell的新手。我正在尝试编写一个程序,该程序采用两个值和一个列表,并将第二个值的列表中的第一个值的每个实例替换。例如。 repOcc 'n' 'i' "pink"将返回"piik"Haskell用另一个值替换列表中的值

以下是我的代码:

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. 
+1

请注明代码从您的期望如何偏离:

repOcc :: Eq t => t -> t -> [t] -> [t] repOcc x y ls = map (\h -> if h == x then y else h) ls 

我们可以进一步通过使ETA - 还原的使用提高了代码。是否有编译器错误?那是什么错误?程序是否输出错误?什么是输入和错误输出的例子? – erisco

+0

开始更简单:如果'x'等于'from'和'x'等于否则不变,您可以编写一个函数f from to x',计算为'to'? – Ryan

+0

在编译时,我得到一个解析错误,编译器建议我在'do block'中添加'let' – RNee

回答

3

你的程序看起来相当“势在必行”,而Haskell的目标是更多的“ 声明式“。所以你不能在列表中设置一个变量z:一旦列表被构建,你就不能再修改它了。因此,您必须构建一个新列表,其中等于x的元素设置为y

接下来您使用(==)函数。该函数在Eq typeclass中定义,因此您需要将Eq t作为类型约束添加到签名。

所以现在我们可以开始构建这样的功能。通常在使用列表时,我们使用递归。递归的基本情况通常是空列表。如果我们遇到空列表,我们应该返回一个空列表,不管xy是什么。因此,我们使用下划线为“不在乎”模式,并使用[]作为列表模式,并写上:

repOcc _ _ [] = [] 

递归情况是,当列表包含头h,并在尾部t(h:t)模式。在这种情况下,我们检查h是否等于x。如果是,我们构建一个以y为头的列表,否则h仍然是头。

repOcc x y (h:t) | x == h = y : tl 
       | otherwise = h : tl 

现在问题仍然是结果列表tl的尾部应该是什么。这里我们使用递归,所以我们称之为repOccx 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 = map (\h -> if h == x then y else h) 
相关问题