Not sure how you reached that number. The Elm code, with blank lines removed, is less than 320 lines. Given the incredibly spacious style its written in, I'd definitely say 300 rather than 400.
But sure, that's still a lot. Part of it is that Elm lacks the proper generics support (which you can observe in the function names) and part is that the archotecture chosen by the creator may not be optimal in terms of maintainability. For example,
type Cell = NotOwned CellLocation | OwnedBy CellLocation Player
and I think, why not type Cell = Cell Location (Maybe Player)
? Its isomorphic (carries the same information) and it removes the need for the complicated getters.