簡體   English   中英

Haskell語法,解析假人的錯誤

[英]Haskell syntax, parse errors for dummies

今天我讀了很多關於Haskell的內容,但這種格式化讓我發瘋。 我想盡快理解我的基本錯誤,這樣我就可以正常開始編碼了。 這里的函數應該返回一個以下一個“math Sign”示例字符串(2sdwds+asd)+3字符串(2sdwds+asd)+3應該返回+asd)+3 這是代碼

getToNextSign :: String -> String 
getToNextSign str = do

let mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']
let a = head str
if a `elem` mathSigns 
 then str
 else if tail str /= [] 
       then getToNextSign $ tail str
       else []

main = do
putStrLn $ getToNextSign "(2sdwds+asd)+3"

它給了我“輸入上的解析錯誤=”。 我也不確定如何在main中調用它,我真的需要putStrLn函數。 我不認為我需要它,但我嘗試了2874種不同的方式來寫這個,現在我放棄了,需要幫助。

除了Stephen Diehl提供的格式改進之外,還可以進行其他改進。 正如Carl指出的那樣,你可以用守衛替換if-else if-else,如下所示:

getToNextSign :: String -> String
getToNextSign str
  | a `elem` mathSigns = str
  | tail str /= []     = getToNextSign $ tail str
  | otherwise          = []
  where
    a = head str
    mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']

當你在它時,你也可以用模式匹配替換頭/尾,如

getToNextSign :: String -> String
getToNextSign (c:cs)
  | c `elem` mathSigns = c:cs
  | not (null cs)      = getToNextSign cs
  | otherwise          = []
  where
    mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']

如果你要進行模式匹配,你也可以一直采用它。

getToNextSign :: String -> String
getToNextSign str = case str of
     c:_ | c `elem` mathSigns -> str
     c:[] -> []
     _:cs -> getToNextSign cs
  where mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']

當你這樣做時,你會發現當getToNextSign獲取一個空列表作為參數時你還沒有真正處理過這種情況,這可能是你想要做的事情。

這是使用Prelude列表函數dropWhileelem一個更簡單的替代方法,它有一個sig類型(a -> Bool) -> [a] -> [a] 它需要一個函數,只要函數提供的條件為真,就會從列表中刪除元素。

因此,您的功能可以重寫如下。

let getNextSign x = dropWhile  ( not . `elem` "+-*/^)" ) x

盡可能避免顯式遞歸,並將它們放在更高階函數中以便充分利用。 Prelude有大量的列表操作功能,它們總是派上用場。

Haskell,對空白敏感,必須讓函數的主體縮進到頂層之外。 對原始代碼的直接修復將是:

getToNextSign :: String -> String
getToNextSign str = do
  let mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']
  let a = head str
  if a `elem` mathSigns
   then str
   else if tail str /= []
         then getToNextSign $ tail str
         else []

main = do
  putStrLn $ getToNextSign "(2sdwds+asd)+3"

正如評論中指出的那樣,因為你沒有使用monad,所以你不需要在這里做表示法。 let語句可以寫成where語句。

getToNextSign :: String -> String
getToNextSign str =
  if a `elem` mathSigns
   then str
   else if tail str /= []
         then getToNextSign $ tail str
         else []
  where
    a = head str
    mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM