[Haskell-cafe] Over general types are too easy to make.
timothyhobbs at seznam.cz
timothyhobbs at seznam.cz
Sun Sep 2 12:35:16 CEST 2012
The problem with the last example I gave is evident in your statement "It
appears you need to distinguish between Bars and Frogs". I have written
quite a number of largish code bases, and I've run into the following
problem every time:
case largeMultiConstructorTypedValue of
Foo{blah=blah,brg=brg} -> .... Some large block...
Bar{lolz=lolz,foofoo=foofoo} -> ...Another large block...
Frog{legs=legs,heads=heads} -> Yet another large block...
Where the obvious re-factor is:
case largeMultiConstructorTypedValue of
foo at Foo -> processFoo foo
bar at Bar -> processBar bar
frog at Frog -> processFrog frog
processFoo :: Foo -> SomeType
processBar :: Bar -> SomeType
processFrog:: Frog -> SomeType
I always want to be able to make procssFoo, processBar, and processFrog
typestrict to their associated constructors. Otherwise they are doomed to
be incomplete functions.
It seems to be a probability approaching law, that I run into this for a
given multi-constructor type. Regardless of it's purpose.
Timothy
---------- Původní zpráva ----------
Od: Tim Docker <tim at dockerz.net>
Datum: 2. 9. 2012
Předmět: Re: [Haskell-cafe] Over general types are too easy to make.
"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
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe at haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
(http://www.haskell.org/mailman/listinfo/haskell-cafe)"
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20120902/a0bd1075/attachment.htm>
More information about the Haskell-Cafe
mailing list