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