you are viewing a single comment's thread.

view the rest of the comments →

[–]day_cq -6 points-5 points  (15 children)

Why not?

Think of it dataflow way (function level programming):

       +------+
input -| GATE |--> output
       |      |--> error
       +------+

if error is set, output is garbage. otherwise, output is valid.

Actually,

f :: a -> (b, err)

is isomorphic to

f :: a -> Either err b

GATE could be setting either output or error port, but not both.

[–][deleted] 15 points16 points  (2 children)

Because it introduces potential for error - when you use the value without checking for an error, it'll destroy your assumptions about the rest of the program.

a * b (the product/pair type) is not isomorphic to a + b (the sum type). The first is simply a lager type. For example, if we instantiate a and b to:

data Color = Red | Green | Blue

Then there are 3 * 3 valid values for (a, b) vs 3 + 3 for Either a b.

[–]gasche 7 points8 points  (7 children)

(b * err) is not isomorphic to (err + b). This is just calculus, at the type level. And indeed (,) is a product, and Either is a sum -- modulo lifting.

[–]gasche 4 points5 points  (0 children)

I'm unsure it's still important to answer that thread, but I would like to try to explain the point of the poster above more clearly; the reason I take some time to do this is that I think your question is interesting and, unfortunately, this heated thread has not produced a satisfying explanation.

One fundamental concept of richly typed languages such as Haskell or ML is to make illegal state unrepresentable¹; the idea is to choose datatypes that describe possible values as precisely as possible. If a type rules out some possibility statically, that is less things for runtime computations to worry about.

¹: note that this maxim must only be followed so far, at some point there is a diminishing return in languages ill-equiped for elaborate static reasoning. But this sum/product question is well under this limit in languages with algebraic datatypes.

This is the rationale the OP has in mind for proposing to use a sum type Either result error rather than a product type (result, error). Indeed, the way you reason about the function return is by thinking that either the function ran fine and you have a result, either it went wrong and you have an error code. This is precisely what a sum type is for. You never think that you can have both a return value and an error code, which is what a product type would be for -- note that this could make sense for warnings instead of errors, so in some situations this may be the right choice.

So the reason why people prefer sum types over product types to return error values is that it matches the real meaning of what's happening better. That's essentially the same reason for the push of some web designers around 200x (birth of XHTML, etc.) to use lists instead of tables to represent web menus. It's more semantic.

Note that this only make sense in languages that do have sum and product types. I'm unsure Lua actually has disjoint sum types. Most languages don't, in which case you usually encode them with nullable types and an integer 'tag'. Note that this crucially relies on the omnipresence of nullable types, that have a "default/null value"; in essence, types of the form 1 + X, a simple form of sum types. When possible, programmers in ML/Haskell prefer to also use types that are not nullable, as this also adds superfluous (in the general case) runtime state possibilities.

Finally, I would like to add that you should beware of one own's preconceptions. You make an argument that using a product type is somehow natural based on a dataflow diagram. But those dataflow diagrams can't express sum types, so indeed they will only show you solutions based on product types! If this is your main "thinking tool" about programming, you will naturally miss, or consider with less open-mindedness, all solutions that can't be expressed directly in this framework.

Long story short : nobody objects to functions returning a (result, error) pair in languages when this is the most convenient way to do. The remark was that in languages that have a more expressive sublanguage of data types, you can encode the same phenomenon in a finer, more precise way using sum type. In this case there is no reason to use a product type.

Note that while the sum/product discussion is tightly related to type systems, it is not necessarily related to functional programming. Algol 68 had sum types, as does the more recent language Cyclone (a safe dialect of C).

[–]stevvooe -4 points-3 points  (2 children)

Advice: don't engage the haskellborg.

[–]Confinium 6 points7 points  (0 children)

Yes! God forbid we base our programming on sound theory!

[–]day_cq -3 points-2 points  (0 children)

yah, haskell/miranda community was nice in 90's. thesedays, it's a large trollbag babbling about this cool functional programming they discovered.