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