In [1]:
import Data.List
import Data.Maybe
import qualified Data.Set as Set

In [2]:
isMadeOf :: String -> Set.Set String -> Bool
isMadeOf word otherWords =
    let
        allSplits = tail $ init $ zip (inits word) (tails word) 
        isValidSplit (left, right) =
            left `Set.member` otherWords &&
            (right `Set.member` otherWords || right `isMadeOf` otherWords)
    in
        any isValidSplit allSplits

In [3]:
longestWord :: [String] -> Maybe String
longestWord xs =
    listToMaybe $ filter (`isMadeOf` Set.fromList xs) $ reverse $ sortOn length xs

In [4]:
longestWord ["cat", "banana", "dog", "nana", "walk", "walker", "dogwalker"]


Just"dogwalker"