Question

I am trying to work through the exercises in Write Yourself a Scheme in 48 Hours. I need help with simplifying couple of functions.

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

The isNumber and isString functions have lot common structure. How do I go about factoring out this common structure?

Was it helpful?

Solution

While you can't parameterize the pattern match itself, you can write yourself small helper functions so you at least don't have to repeat the list handling for every function:

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

In my opinion, the special case handling of the empty list isn't consistent here. You should consider just using all instead (so that the empty list can be a list of any kind, similar to how Haskell's lists work).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top