haskelllive/haskelllive — pull request #20 by jb55 (2012-08-20 05:44:09+00:00)
Title: Some more refactoring + ideas

I'm not expecting this to be pulled, it's just here to show some more possible refactorings. Some more advanced than others:

### Invert lookup table

```haskell
typeToChar :: PType -> Char
typeToChar Pawn = 'p'
typeToChar Knight = 'k'
typeToChar Bishop = 'b'
typeToChar Rook = 'r'
typeToChar Queen = 'q'
typeToChar King = 'k'

typeList :: [(Char, PType)]
typeList = map (typeToChar &&& id) (enumFrom Pawn)
```

This introduces a few new concepts including `(&&&)` and `enumFrom`. I tend to prefer writing my lookup tables this way because the compiler can catch new cases and you only have to update it in one place.

### Show piece refactored

```haskell
colorChar :: PColor -> Char -> Char
colorChar White = toUpper
colorChar Black = toLower

showPiece :: Piece -> Char
showPiece (Piece color ptype) = colorChar color . typeToChar $ ptype
```

### Read piece refactored

```haskell
charColor :: Char -> PColor
charColor c | isUpper c = White
| otherwise = Black

readPiece :: Char -> Maybe Piece
readPiece c = Piece <$> Just (charColor c) <*> charToType c
```

This introduces pattern guards and applicative functors

### Phantom types

A little more advanced and somewhat contrived for this application. I take the colored character idea a step further and introduce a

```haskell
data Black
data White
newtype ColoredChar a = ColoredChar { unCC :: Char }
```

newtype which tags characters with White and Black phantom types when they've been converted to upper or lower case. This adds another layer of type safety when passing `Char`s around to different functions. For example, the lookup table is really a lookup table of `[(ColoredChar White, PType)]` so we can enforce that in the phantom type. Now the lookup function will only accept chars that have been uppercased with this function:

```haskell
colorCharWhite :: Char -> ColoredChar White
colorCharWhite = ColoredChar . colorChar White
-- remembering that "colorChar White" is just "toUpper"
```

Again, somewhat contrived for this application but its something I wish I learned earlier!