Design of data types in Haskell
algebraic-data-types, haskell
Solution
I prefer something like:
data Direction = Left | Right
data Move = Walk Direction | Jump
type Action = Maybe Move
type ActionList = [Action]
charToAction :: Char -> Action
charToAction c = case c of
'q' -> Just $ Walk Left
'd' -> Just $ Walk Right
'z' -> Just $ Jump
_ -> Nothing
stringToActions :: String -> ActionList
stringToActions = map charToAction
under the principle that each data type clearly explains its own purpose, and doesn't "assume" anything about how it might be used. Some counter-examples:
newtype Direction = Direction Bool
data Move = Stationary | Walk Direction | Jump
Here, `Direction` doesn't really explain what it means... does it mean you have a direction or you don't have a direction? Hmmm! Also, what happens when you need `Up` and `Down`? It's hard to extend your program if `Direction` is just a `Bool`.
And `Move` has a data constructor `Stationary` here that isn't actually a move at all. You "leak" the notion that some keystrokes won't result in a move. Again that will end up complicating your code.
Make sense?
Problem
Which do you suggest: ``` data Direction = Left | Right type Direction = Bool newtype Direction = Direction Bool ``` Then I'm making: ``` data Move = WalkRight Bool | Jump ``` or ``` data Move = Walk Direction | Jump ``` depending of the previous answer. I have a function of type `Char -> Maybe Move`: ``` charToAction 'q' = Just $ WalkRight False charToAction 'd' = Just $ WalkRight True charToAction 'z' = Just Jump charToAction _ = Nothing ``` Should I change my type `Move` into: ``` data Move = Stationary | WalkRight Bool | Jump ``` ? The function would become: ``` charToAction 'q' = WalkRight False charToAction 'd' = WalkRight True charToAction 'z' = Jump charToAction _ = Stationary ``` I wonder this because the list doesn't need a Maybe: ``` data [a] = [] | a : [a] ``` Or is there a way to derive `Maybe` to make it cleaner?