<html><body><p>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:</p><p><br></p><p>case largeMultiConstructorTypedValue of</p><p>&nbsp;&nbsp; Foo{blah=blah,brg=brg} -&gt; .... Some large block...</p><p>&nbsp;&nbsp; Bar{lolz=lolz,foofoo=foofoo} -&gt; ...Another large block...</p><p>&nbsp;&nbsp; Frog{legs=legs,heads=heads} -&gt; Yet another large block...</p><p><br></p><p>Where the obvious re-factor is:<br></p><p><br></p><p>case largeMultiConstructorTypedValue of</p><p>&nbsp;&nbsp; foo@Foo -&gt; processFoo foo<br></p><p>&nbsp;&nbsp; bar@Bar -&gt; processBar bar<br></p><p>&nbsp;&nbsp; frog@Frog -&gt; processFrog frog</p><p><br></p><p>processFoo :: Foo -&gt; SomeType</p><p>processBar :: Bar -&gt; SomeType</p><p>processFrog:: Frog -&gt; SomeType</p><p><br></p><p>I always want to be able to make procssFoo, processBar, and processFrog typestrict to their associated constructors.&nbsp; Otherwise they are doomed to be incomplete functions.</p><p><br></p><p>It seems to be a probability approaching law, that I run into 
this for a given multi-constructor type. Regardless of it's purpose.</p><p><br></p><p>Timothy</p><p><br></p><p>---------- Původní zpráva ----------<br>Od: Tim Docker &lt;tim@dockerz.net&gt;<br>Datum: 2. 9. 2012<br>Předmět: Re: [Haskell-cafe] Over general types are too easy to make.</p><blockquote>On 01/09/12 04:00, timothyhobbs@seznam.cz wrote:<br>&gt; I'd have to say that there is one(and only one) issue in Haskell that <br>&gt; bugs me to the point where I start to think it's a design flaw:<br>&gt;<br>&gt; It's much easier to type things over generally than it is to type <br>&gt; things correctly.<br>&gt;<br>&gt; Say we have a<br>&gt;<br>&gt; &gt;data BadFoo =<br>&gt; &gt; BadBar{<br>&gt; &gt;  badFoo::Int} |<br>&gt; &gt; BadFrog{<br>&gt; &gt;  badFrog::String,<br>&gt; &gt;  badChicken::Int}<br>&gt;<br>&gt; This is fine, until we want to write a function that acts on Frogs but <br>&gt; not on Bars.  The best we can do is throw a runtime error when passed <br>&gt; a Bar and not a Foo:<br>&gt;<br>&gt; &gt;deBadFrog :: BadFoo -&gt; String<br>&gt; &gt;deBadFrog (BadFrog s _) = s<br>&gt; &gt;deBadFrog BadBar{}      = error "Error: This is not a frog."<br>&gt;<br>&gt; We cannot type our function such that it only takes Frogs and not <br>&gt; Bars.  This makes what should be a trivial compile time error into a <br>&gt; nasty runtime one :(<br>&gt;<br>&gt; The only solution I have found to this is a rather ugly one:<br>&gt;<br>&gt; &gt;data Foo = Bar BarT | Frog FrogT<br>&gt;<br>&gt; If I then create new types for each data constructor.<br>&gt;<br>&gt; &gt;data FrogT = FrogT{<br>&gt; &gt; frog::String,<br>&gt; &gt; chicken::Int}<br>&gt;<br>&gt; &gt;data BarT = BarT{<br>&gt; &gt; foo :: Int}<br>&gt;<br>&gt; Then I can type deFrog correctly.<br>&gt;<br>&gt; &gt;deFrog :: FrogT -&gt; String<br>&gt; &gt;deFrog (FrogT s _) = s<br>&gt;<br><br>I'm curious as to what you find ugly about this. It appears you need to <br>distinguish between Bars and Frogs, so making them separate types (and <br>having a 3rd type representing the union) is a natural haskell solution:<br><br>   data Bar = ..<br>   data Frog = ..<br><br>   fn1 :: Bar -&gt; ..<br>   fn2 :: Frog -&gt; ..<br>   fn3 :: Either Bar Frog -&gt; ..<br><br>Perhaps a more concrete example would better illustrate your problem?<br><br>Tim<br><br><br><br><br><br>_______________________________________________<br>Haskell-Cafe mailing list<br>Haskell-Cafe@haskell.org<br><a href="http://www.haskell.org/mailman/listinfo/haskell-cafe">http://www.haskell.org/mailman/listinfo/haskell-cafe</a></blockquote></body></html>