Cabbage-Goat-Wolf puzzle in Haskell
Haskell's record system is not really good at providing you uniform access to record entries. That is the reason your findMoves implementation has to be so verbose: You cannot generalize over the fields.

There are a number of ways to get around that. One could be using a library such as fclabels that facilitates this job for you. You set it up like follows:

import Data.Record.Label

data Pos = ....

$( mkLabels [''Pos] )


This will give you "labels" with names such as lCabb that you can use with functions such as getL or modL. Without all this boilerplate, it is possible to write a much more satisfying findMoves function:

findMoves :: Pos -&gt; [Pos]
findMoves pos = filter valid moves
  where
    moves    = [ foldr (\obj -&gt; modL obj opp) pos objs
               | objs &lt;- moveComb, same $ map (`getL` pos) objs
               ]
    moveComb = [[lCabb, lFarmer], [lGoat, lFarmer], [lWolf, lFarmer], [lFarmer]]
    same xs  = all (== head xs) xs