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?

Original source