[Haskell-cafe] Avoiding parametric function binding

Kevin Quick quick at sparq.org
Sat Dec 31 16:09:24 CET 2011


I'm having some difficulty avoiding a tight parametric binding of function  
parameters, which is limiting the (de)composability of my expressions.   
I'm curious as to whether there is an option or method I haven't tried to  
achieve this.

Here's an example test case:

> data Var = V1 (Maybe Int)
>          | V2 (Maybe String)
>
> test = V1 (Just 1)

Given this structure, I can do something like this:

> elemStr :: (Show a) => Maybe a -> String
> elemStr = show
>
> varStr (V1 x) = elemStr $ id x
> varStr (V2 x) = elemStr $ id x
>
> main = putStrLn . varStr $ test

This operation extracted the internal value from the Var container, and  
then passes it to a parametric function (id) and that result to another  
parametric function with a class restriction on the input.  This is fine  
so-far.

However, what I'd like to do is decompose this to allow more flexibility  
(using id is pretty boring) without having to repeat the extraction  
boilerplate each time.  My first attempt:

> varElem :: forall x . (Show x) => Var -> x
> varElem (V1 x) = x
> varElem (V2 x) = x
>
> main = putStrLn . elemStr . varElem $ test

This fails because even though I've specified the same class constraint  
for the output type of varElem that elemStr requires on its input element,  
the compiler binds the parametric type of x when it processes the first  
(V1) definition and fails with an error on the second definition because  
it asserts that x must be an Int and it found a String.

I realized that the parametric output type was awkward, so I tried  
inverting the design (somewhat similar to fmap):

> onVarElem :: forall a . (Show a) => (Maybe a -> String) -> Var -> String
> onVarElem f (V1 x) = f x
> onVarElem f (V2 x) = f x
>
> main = putStrLn . onVarElem elemStr $ test

This is probably a better design, but still fails for the same reason:

     Couldn't match expected type `Int' with actual type `[Char]'
     Expected type: Maybe Int
       Actual type: Maybe String
     In the first argument of `f', namely `x'
     In the expression: f x

Even changing onVarElem so the second parameter was a simple variable and  
performing the pattern match in an internal where or let binding failed  
because the first application of f bind its parametric values.

Is there a way to delay this parametric binding to allow composable  
function specifications?

Thanks,
   Kevin

-- 
-KQ



More information about the Haskell-Cafe mailing list