2017-08-27 124 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) 
相關問題