extractPatternStrings ∷ IO [(Map String SqlValue)] → IO [String]
An IO [String] is an IO action that produces a [String] result. Your use of do notation ensures extractPatternStrings produces an IO [String], not a [String].
An IO [(Map String SqlValue)] is an IO action that produces a [Map String SqlValue] result. But you cannot pattern match against an IO action. The syntax you use is for matching directly against a list, not against an IO action that produces a list.
You should use this type signature instead:
extractPatternStrings ∷ [Map String SqlValue] → IO [String]
Except that, as @missingno points out, this doesn't need to be an IO action:
extractPatternStrings ∷ [Map String SqlValue] → [String]
extractPatternStrings [] = []
extractPatternStrings (m:ms) = toString m : extractPatternStrings ms
where
toString ∷ Map String SqlValue → String
toString m = (fromSql . fromJust . (Map.lookup "word"))∷ String
Or, better (and fixing an error in toString):
extractPatternStrings ∷ [Map String SqlValue] → [String]
extractPatternStrings = map toString
where
toString ∷ Map String SqlValue → String
toString = fromSql . fromJust . Map.lookup "word"
More succinctly:
extractPatternStrings ∷ [Map String SqlValue] → [String]
extractPatternStrings = map (fromSql . fromJust . Map.lookup "word")
If you really must have the original signature, then use liftM, either by changing your calling code to selectAll ↠ liftM extractPatternStrings (and I must confess I don't recognise the operator you use there), or by defining extractPatternStrings as
extractPatternStrings ∷ IO [Map String SqlValue] → IO [String]
extractPatternStrings = liftM $ map (fromSql . fromJust . Map.lookup "word")
But I recommend the former.