Using field selectors in a type constructor

Graham Klyne gk at ninebynine.org
Wed Oct 15 11:45:07 EDT 2003


At 18:38 14/10/03 -0700, Brandon Michael Moore wrote:
>On Mon, 13 Oct 2003, Graham Klyne wrote:
>
> > 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.

Almost!  Using 'this' to label the value being defined, I had to add an "in 
this" at the end, thus:
[[
joinVarBindings :: (Eq a) => VarBinding a b -> VarBinding a b -> VarBinding a b
joinVarBindings vb1 vb2
     | vbNull vb1 = vb2
     | vbNull vb2 = vb1
     | otherwise  = let
         this = VarBinding
             { vbMap  = headOrNothing . filter isJust . flist [ vbMap vb1, 
vbMap vb2 ]
             , vbEnum = map (\v -> (v,fromJust (vbMap this v))) $
                        boundVars vb1 `union` boundVars vb2
             , vbNull = False
             }
         in this
]]

(Getting the layout just right here proved to be a minor challenge)

I hadn't thought of using 'let' in this way, and this led me to wondering 
if a form of do might be used...

Out of curiosity, I also tried this:
[[
joinVarBindings :: (Eq a) => VarBinding a b -> VarBinding a b -> VarBinding a b
joinVarBindings vb1 vb2
     | vbNull vb1 = vb2
     | vbNull vb2 = vb1
     | otherwise  = do
         { let this = VarBinding
                 { vbMap  = headOrNothing . filter isJust . flist [ vbMap 
vb1, vbMap vb2 ]
                 , vbEnum = map (\v -> (v,fromJust (vbMap this v))) $
                            boundVars vb1 `union` boundVars vb2
                 , vbNull = False
                 }
         ; this
         }
]]

which according to the Haskell report (p29) should translate to just the 
previous example, but Hugs reports a "cannot justify constraints" error ... 
it seems to want VarBindings to be a Monad, even though the translation to 
a non-do form can be achieved without invoking any monadic operator.  Is 
this a bug?

Thanks!

#g


------------
Graham Klyne
For email:
http://www.ninebynine.org/#Contact



More information about the Haskell-Cafe mailing list