2012-04-15 61 views
4

我正在努力通過Write Yourself a Scheme in 48 Hours的練習。我需要簡化幾個函數的幫助。哈斯克爾 - 請幫我簡化這兩個功能

data LispVal = Number Integer 
      | String String 
      | Bool Bool 

isNumber :: [LispVal] -> LispVal 
isNumber []    = Bool False 
isNumber [(Number _)]  = Bool True 
isNumber ((Number _):xs) = isNumber xs 
isNumber _    = Bool False 

isString :: [LispVal] -> LispVal 
isString []    = Bool False 
isString [(String _)]  = Bool True 
isString ((String _):xs) = isString xs 
isString _    = Bool False 

isNumberisString功能有很多共同的結構。我如何去分解這個共同的結構?

+0

模式匹配無法移動和因式分解。所以字符串和數字文字必須寫在「現場」。我不確定你想要做什麼,但是你也許可以實現一個'typeOf :: [LispVal] - > LispType'函數,它可以一次模式匹配表達式並返回它的類型。 – 2012-04-15 20:38:49

+3

您可以移除第一個案例(空列表),因爲它也是由最後一個模式捕獲的。 – 2012-04-15 21:02:17

回答

6

雖然你不能參數化模式匹配本身,你可以自己寫的小助手功能,因此你至少不必重複列表處理爲每個函數:

isString (String _) = True 
isString _ = False 

isNumber (Number _) = True 
isNumber _ = False 

all1 _ [] = False 
all1 f xs = all f xs 

isListOfStrings = Bool . all1 isString 
isListOfNumbers = Bool . all1 isNumber 

在我看來,空列表的特殊情況處理在這裏不一致。你應該考慮使用all來代替(這樣空列表可以是任何類型的列表,類似於Haskell列表的工作方式)。

+3

這些賦予'Bool True'一個空列表,但OP希望'Bool False'。 – dave4420 2012-04-15 21:07:43

+3

@dave:謝謝......這沒有任何意義,但我改變了它。 – 2012-04-15 21:09:44