On 01/09/12 04:00, timothyho...@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





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

Reply via email to