[Haskell-cafe] Over general types are too easy to make.

Tim Docker tim at dockerz.net
Sun Sep 2 12:13:34 CEST 2012


On 01/09/12 04:00, timothyhobbs at seznam.cz wrote:
> I'd have to say that there is one(and only one) issue in Haskell that 
> bugs me to the point where I start to think it's a design flaw:
>
> It's much easier to type things over generally than it is to type 
> things correctly.
>
> Say we have a
>
> >data BadFoo =
> > BadBar{
> >  badFoo::Int} |
> > BadFrog{
> >  badFrog::String,
> >  badChicken::Int}
>
> This is fine, until we want to write a function that acts on Frogs but 
> not on Bars.  The best we can do is throw a runtime error when passed 
> a Bar and not a Foo:
>
> >deBadFrog :: BadFoo -> String
> >deBadFrog (BadFrog s _) = s
> >deBadFrog BadBar{}      = error "Error: This is not a frog."
>
> We cannot type our function such that it only takes Frogs and not 
> Bars.  This makes what should be a trivial compile time error into a 
> nasty runtime one :(
>
> The only solution I have found to this is a rather ugly one:
>
> >data Foo = Bar BarT | Frog FrogT
>
> If I then create new types for each data constructor.
>
> >data FrogT = FrogT{
> > frog::String,
> > chicken::Int}
>
> >data BarT = BarT{
> > foo :: Int}
>
> Then I can type deFrog correctly.
>
> >deFrog :: FrogT -> String
> >deFrog (FrogT s _) = s
>

I'm curious as to what you find ugly about this. It appears you need to 
distinguish between Bars and Frogs, so making them separate types (and 
having a 3rd type representing the union) is a natural haskell solution:

   data Bar = ..
   data Frog = ..

   fn1 :: Bar -> ..
   fn2 :: Frog -> ..
   fn3 :: Either Bar Frog -> ..

Perhaps a more concrete example would better illustrate your problem?

Tim







More information about the Haskell-Cafe mailing list