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

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to