マップの通りぬけ

import Data.Maybe (fromJust)
import System (getArgs)
import Control.Monad (liftM)

type Point = ((Int,Int),Char)
data Direction = N | S | W | E deriving (Eq, Show)

direction d = fromJust $ lookup d [(N,[E,N,W,S]),(S,[W,S,E,N]),(W,[N,W,S,E]),(E,[S,E,N,W])]

move :: Direction -> Point -> [Point] -> Maybe Point
move N p@((x,y),_) ps | y == 0 = Nothing
                      | otherwise = move' (\(x,y) -> (x,y-1)) p ps
move S p@((x,y),_) ps | y == snd (fst (last ps)) = Nothing
                      | otherwise = move' (\(x,y) -> (x,y+1)) p ps
move W p@((x,y),_) ps | x == 0 = Nothing
                      | otherwise = move' (\(x,y) -> (x-1,y)) p ps
move E p@((x,y),_) ps | x == fst (fst (last ps)) = Nothing
                      | otherwise = move' (\(x,y) -> (x+1,y)) p ps

move' f p ps = case lookup p' ps of
                 Just '.' -> Nothing
                 Just '+' -> Just (p','+') 
  where p' = f $ fst p

start _ (_,'.') _ = False
start d p ps = let ds = direction d in next ds p ps
  where next [] p ps     = False
        next (d:ds) p ps = case move d p ps of
                             Nothing -> next ds p ps
                             Just p' -> check_and_go d p' ps
        check_and_go d q qs = if snd (fst q) == snd (fst (last ps)) then True
                              else if q == p then False else next (direction d) q qs

mapToPoints :: [String] -> [[Point]]
mapToPoints = f 0
  where f _ [] = []
        f n (x:xs) = g 0 n x:(f (n + 1) xs)
        g _ _ [] = []
        g n m (x:xs) = ((n,m),x):g (n + 1) m xs

main = do
     (f:_) <- getArgs
     xss@(x:_) <- liftM (mapToPoints . lines) (readFile f)
     print $ or $ map (\p -> start S p (concat xss)) x