Pattern matching 'undefined'

Alain Cremieux alcremi@pobox.com
Mon, 26 May 2003 23:50:27 +0200


Derek Elkins wrote:

>On Sun, 25 May 2003 23:28:02 +0200
>Alain Cremieux <alcremi@pobox.com> wrote:
>
>  
>
>>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)?)
>  
>

The idea is that the list may be empty, thus the choice of a list of 
pairs instead of a simple pair

>  
>
>>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.
>  
>

How can I do that ? Can you give me an example ?

>  
>
>>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)
>  
>
The problem is that there may be 50 fields (my example was too simple, 
sorry). So I want precisely to avoid 'Just' and 'Nothing', because I 
want to be able to say :
graph = AttrGraphDot {color = Blue}
without having to name the 49 other fields.
Field labels seem really adequate to do this, and by having defined the 
type Color with Red | Blue | ... there will be a compile-time check on 
the correctness of the value. This would be impossible with an ordinary 
implementation : [(String, String)]  which will be verified only at 
run-time.
But then I must be able to convert the field-labelled datatype to a list 
[(String, String)], depending on which labels have been provided.
This is not so easy, especially since it is not possible to 
pattern-match against field labels, which are functions.

Alain