Using field selectors in a type constructor

Brandon Michael Moore brandon at its.caltech.edu
Tue Oct 14 19:38:57 EDT 2003


On Mon, 13 Oct 2003, Graham Klyne wrote:

> I've run across a minor coding niggle on a couple opf accosions when using
> a type constructor with field selectors.  The full code of my test case is
> below.  The value 'test2' evaluates to True.
>
> The function that niggles me is this:
>
> [[
> joinVarBindings :: (Eq a) => VarBinding a b -> VarBinding a b -> VarBinding a b
> joinVarBindings vb1 vb2
>      | vbNull vb1 = vb2
>      | vbNull vb2 = vb1
>      | otherwise  = VarBinding
>          { vbMap  = mv12
>          , vbEnum = map (\v -> (v,fromJust (mv12 v))) $
>                     boundVars vb1 `union` boundVars vb2
>          , vbNull = False
>          }
>      where
>          mv12 = headOrNothing . filter isJust . flist [ vbMap vb1, vbMap vb2 ]
> ]]
>
> Is it really necessary to define mv12 as a separate "where" clause here?
>
> What I'd really like to do is assign it to field vbMap, and reference that
> from the definition of vbEnum, but I can't figure out if there's a way
> to do so.  Writing this:


> Results in a fairly obvious type error:  I'd need to have a way to say that
> vbMap is applied to the value under construction.  Experience with Java would
> suggest maybe something like this:
> [[
>          , vbEnum = map (\v -> (v,fromJust (vbMap this v))) $
> ]]
> but of course Haskell isn't Java.

The natural way to do this is to apply vbMap to the value under
construction, Haskell being lazy and all. Of course this requires
naming the variable under construction it hardly makes a difference
when there is only one subexpression.

[[
joinVarBindings :: (Eq a) => VarBinding a b -> VarBinding a b -> VarBinding a b
joinVarBindings vb1 vb2
     | vbNull vb1 = vb2
     | vbNull vb2 = vb1
     | otherwise  = let vb = VarBinding
         { vbMap  = headOrNothing . filter isJust . flist [ vbMap vb1,
vbMap vb2 ]
         , vbEnum = map (\v -> (v,fromJust (vbMap vb))) $
                    boundVars vb1 `union` boundVars vb2
         , vbNull = False
         }
]]

This should work.

Brandon.



More information about the Haskell-Cafe mailing list