2013-07-27 47 views
1

我不知道如何描述這個標題,但它應該可以用示例代碼來理解。我怎樣才能縮短這個:如何用許多等效模式縮短Haskell函數定義

parse qs ([email protected]  :[email protected](Noun _) :Adv _ f:ss) = parse qs $ e : f t : ss 
parse qs ([email protected]  :[email protected](Verb _ _ _):Adv _ f:ss) = parse qs $ e : f t : ss 
parse qs ([email protected](Asgn _) :[email protected](Noun _) :Adv _ f:ss) = parse qs $ e : f t : ss 
parse qs ([email protected](Asgn _) :[email protected](Verb _ _ _):Adv _ f:ss) = parse qs $ e : f t : ss 
parse qs ([email protected] :[email protected](Noun _) :Adv _ f:ss) = parse qs $ e : f t : ss 
parse qs ([email protected] :[email protected](Verb _ _ _):Adv _ f:ss) = parse qs $ e : f t : ss 
parse qs ([email protected](Adv _ _) :[email protected](Noun _) :Adv _ f:ss) = parse qs $ e : f t : ss 
parse qs ([email protected](Adv _ _) :[email protected](Verb _ _ _):Adv _ f:ss) = parse qs $ e : f t : ss 
parse qs ([email protected](Verb _ _ _):[email protected](Noun _) :Adv _ f:ss) = parse qs $ e : f t : ss 
parse qs ([email protected](Verb _ _ _):[email protected](Verb _ _ _):Adv _ f:ss) = parse qs $ e : f t : ss 
parse qs ([email protected](Noun _) :[email protected](Noun _) :Adv _ f:ss) = parse qs $ e : f t : ss 
parse qs ([email protected](Noun _) :[email protected](Verb _ _ _):Adv _ f:ss) = parse qs $ e : f t : ss 

名單是[Token]類型(如qs,這是在其他定義中使用),這是我自己的類型。是否可能有Token的子類型,僅涵蓋MarkAsgn _,LeftParen,Adv _ _,Verb _ _ _Noun _,並且與該模式匹配?

編輯:的Token定義:

data Token = (Show, Read a) => Noun a 
      | Verb String (Token -> Token) (Token -> Token -> Token) 
      | Adv String (Token -> Token) Token 
      | Conj String (Token -> Token -> Token) Token 
      | Name String 
      | Asgn AsgnType 
      | Mark 
      | LeftParen 
      | RightParen 
    deriving (Show, Read) 
+0

「Token」的完整定義是什麼? –

回答

2

你可以編寫處理模式的一些輔助功能爲你匹配(因爲你實際上並不解構列表中的前兩個元素),然後使用衛士檢查模式是否匹配。

isStartToken :: Token -> Bool 
isStartToken = {- returns True for Mark, Asgn, LeftParen etc -} 

isNounOrVerb :: Token -> Bool 
isNounOrVerb = {- returns True for Noun and Verb only -} 

parse qs (e: t: Adv _ f: ss) 
    | isStartToken e && isNounOrVerb t = parse qs (e : f t : ss) 
    | otherwise      = {- whatever comes here -} 
+0

鑑於我所有的其他模式,'否則'情況可能有點困難,但我會試一試。如果它有效,我會將其標記爲答案。 –

+0

而不是像這樣使用'otherwise',你也可以在'parse qs(e:t:Adv_f:ss)|之後開始一個新的等式。 ... = ...'。 – Toxaris

1

這會更清晰一點,更短:

parse qs ([email protected]:ss) = parse qs $ appNounVerbAdv ss 
parse qs ([email protected](Asgn _):ss) = parse qs $ appNounVerbAdv ss 
parse qs ([email protected]:ss) = parse qs $ appNounVerbAdv ss 
parse qs ([email protected](Adv _ _) :ss) = parse qs $ appNounVerbAdv ss 
parse qs ([email protected](Verb _ _ _):ss) = parse qs $ appNounVerbAdv ss 
parse qs ([email protected](Noun _) :ss) = parse qs $ appNounVerbAdv ss 
... 

appNounVerbAdv ([email protected](Noun _):Adv _ f:ss) = f t : ss 
appNounVerbAdv ([email protected](Verb _ _ _):Adv _ f:ss) = f t : ss 
appNounVerbAdv _ = error "" 

剛剛嘗試向上突破的情況下,爲更小的功能以及這種模式只要你有沒有使用(如在qs參數在上面parse)。

也許像FSM這樣更正式的方法可能有助於保持事物的可管理性?

+0

在實現前面的答案時,我傾向於更像「appNounVerbAdv」的函數。感謝您確認此方法。 –

+0

在FSM的想法,這可能工作。我會牢記這一點,並且可能會試圖用這種風格重寫,如果這種風格不起作用的話。我主要關心的是我的程序要求根據輸入流的方向進行閱讀。我對FSMs知之甚少,不知道它們是否適合這一點。 –