Pattern matching 'undefined'

Derek Elkins ddarius@hotpop.com
Sun, 25 May 2003 18:02:55 -0400


On Sun, 25 May 2003 23:28:02 +0200
Alain Cremieux <alcremi@pobox.com> wrote:

> Hi,
> 
> I want to represent a list of (key, values) in Haskell, where key are 
> predefined strings
> 
> So I define a datatype using field labels :
> 
> data UR = MkUR {
>                  fieldA :: Int,
>                  fieldB :: Int,
>                  fieldC :: String
>                  }
>            deriving (Show)
> 
> and, for example, we have
> 
> testUR  = MkUR {fieldA = 1}
> testUR' = MkUR {fieldA = 2, fieldB = 3, fieldC = "C"}
> 
> Now I want to write a function which transforms my datatype in
> [(String, String)] where a (key, value) element exists if the field is
> present, and none if the field does not exist.
> 
> attrList :: UR -> [(String, String)]
> attrList u =  al "fieldA" (fieldA u)
>            ++ al "fieldB" (fieldB u)
>            ++ al "fieldC" (fieldC u)
>           
> al :: (Show a) => String -> a -> [(String, String)]
> al fn fv = [(fn, show fv)]

(Wouldn't it make more sense to do attrList u = [al "fieldA" (fieldA u),
al ...] with al :: ... -> (String,String)?)

> Of course, as written, "attrList testUR'" succeeds and "attrList
> testUR" fails (Missing field in record construction Main.fieldB)
> I need to match against undefined, which is impossible.

So reify undefined.

> Is there a solution (probably involving irrefutable patterns, ~) ? 

You want values that may or may not be there.  The standard solution is
the Maybe type.  Assuming you don't want to print out, "Just \"C\"", you
can either make your own type with your own instance of show, or use a
showValue function in al.  The latter is likely preferable as there are
quite a few utility functions for the Maybe type already and it's more
familiar.  You can define al with type ... -> Maybe (String,String) and
attrList would just be catMaybes over a list of them, assuming you
want attrList(MkUR (Just 5) Nothing (Just "Hello")) to give you
[("fieldA","5"),("fieldC","\"Hello\"")] otherwise al can be ... ->
(String, Maybe String) and you'd change show fv to fmap show fv, or just
... -> (String,String) with ("fieldB","undefined"/"Nothing"/""/whatever)