Checking whether a word satisfies a template with wildcards
Let's omit the first 3 conditions (for now).

wordFitsTemplate :: Template -&gt; Hand -&gt; String -&gt; Bool
wordFitsTemplate (t:ts) hs []
    | t == '?'                      = wordFitsTemplate ts hs []
    | otherwise                     = False
wordFitsTemplate ('?':ts) hs (s:ss)
    | s `elem` hs                   = wordFitsTemplate ts (delete s hs) ss
    | otherwise                     = False
wordFitsTemplate (t:ts) hs (s:ss)
    | t == s                        = wordFitsTemplate ts hs ss
    | otherwise                     = False


First, we can see that if we have an empty array, we're going to just check if the rest of the string is full of question marks. Let's reduce that case first. (This gives us the additional benefit of covering the case where we are given an empty template and string)

wordFitsTemplate :: Template -&gt; Hand -&gt; String -&gt; Bool
wordFitsTemplate ts hs [] = all (== '?') ts
wordFitsTemplate ('?':ts) hs (s:ss)
    | s `elem` hs                   = wordFitsTemplate ts (delete s hs) ss
    | otherwise                     = False
wordFitsTemplate (t:ts) hs (s:ss)
    | t == s                        = wordFitsTemplate ts hs ss
    | otherwise                     = False


This is sort of messy, so let's introduce a helper function which checks a char from the template and the string. It returns a boolean indicating if it matches and the hand.

charFitsTemplate :: Char -&gt; Hand -&gt; Char -&gt; (Bool, Hand)
charFitsTemplate t hand c
    | t == '?' &amp;&amp; c `elem` hand = (True, delete c hand)
    | otherwise = (t == c, hand)


Let's redefine our wordFitsTemplate function now.

wordFitsTemplate :: Template -&gt; Hand -&gt; String -&gt; Bool
wordFitsTemplate ts _ [] = all (== '?') ts
wordFitsTemplate (t:ts) hand (c:cs) = isFit &amp;&amp; wordFitsTemplate ts newHand cs
    where (isFit, newHand) = charFitsTemplate hand t c
wordFitsTemplate _ _ _ = False


It should be noted that when isFit evaluates to False, the function returns False; otherwise, when it evaluates to True, the result of the function depends on wordFitsTemplate ts newHand. Hence, we can combine them using &amp;&amp;.

This is the closest I could get to a nice solution. :) In functional programming, it's best to think of how to compartmentalize the problem and make it more elegant. In this case, we seperated the checking of whether a character matches (as well as the hand handling, no pun intended) with checking the template string. This gives us a rather elegant solution.