Pangram Checker in Haskell

67 Views Asked by At

I was wondering how to check whether a string is a pangram, as a beginner's exercise. I have two solutions, but I don't understand them at all.

Version 1

import Data.Char (toLower)

isPangram :: String -> Bool
isPangram str = all (`elem` map toLower str) ['a'..'z']

Version 2

import Data.Char (toLower)

isPangram :: String -> Bool
isPangram str = allPresent (map toLower str) ['a'..'z']

allPresent :: String -> String -> Bool
allPresent _ [] = True
allPresent [] _ = False
allPresent (x:xs) ys
    | x `elem` ys = allPresent xs ys
    | otherwise = False

Not sure if they're correct, but any help to simplify or modify this would be appreciated!

1

There are 1 best solutions below

4
willeM_ Van Onsem On

Your second version is not. That should be:

isPangram :: String -> Bool
isPangram str = allPresent ['a' .. 'z'] (map toLower str)

allPresent :: String -> String -> Bool
allPresent [] _ = True
allPresent _ [] = False
allPresent (x : xs) ys
  | x `elem` ys = allPresent xs ys
  | otherwise = False

Indeed, for a pangram you check if all characters belong to the string. But that is not symmetrical: checking if all elements of X belong to Y is not equivalent to checking if all elements of Y belong to X. We here thus use the first list as the collection of items where we check if each item x of that collection, is an element of the second collection ys.

We thus call allPresent ['a' .. 'z'] (map toLower str) so the first list contains all lowercase characters, the second the lowercase version of the input str. In case the first list is empty, we are done, so we can return True. In case it is not, and the second list is empty, we know it will be False. If both lists are not empty, we check if the first item x of the list is a member of ys, and if so recurse with the rest of the elements xs; otherwise we can return False.