4 ms·
I Love Haskell but I think sometimes people give it more credit than deserved. So you say > int foo(int, int); Doesn't tell you anything. Ok, you are right! B
by BSousa 13y ago
I Love Haskell but I think sometimes people give it more credit than deserved. So you say
> int foo(int, int);
Doesn't tell you anything. Ok, you are right! But that code translated to Haskell would be:
> foo :: Int -> Int -> Int
How does that give you more information about foo than the C code above?
Now if you say you use type synonyms in Haskell, I would agree, but you can use typedefs in C as well.
- nightski 13y agoWell it does tell you that there are no IO computations with side effects. So you really are restricted to the Int type and the operations that can be performed on it. You get much stronger statements by using type variables (not type synonyms). This is actually laid out rather clearly in Theorems for Free by Wadler[1]. The essence is that the more generic a type signature gets, the more you can reason about it's behavior. Since if you want to perform (+) (-) (*) (/) for example you'll need to include a (Num) constraint. [1] http://ttic.uchicago.edu/~dreyer/course/papers/wadler.pdf http://ttic.uchicago.edu/~dreyer/course/papers/wadler.pdf
- jlarocco 13y ago> So you really are restricted to the Int type and the operations that can be performed on it. That's so vague it's almost meaningless, and doesn't support the original assertion, which was "But with HASKELL, with just the type signature you can write a program that does what you want even though you don't know what the components you used do!" Even given a simple thing like foo:: int -> int -> int, there's really no way to tell what it's doing. It could be multiplying the arguments together, dividing, adding, computing psuedo-random numbers using two seed values, ... Not only that, but I'm not sure it's true that it's limited to the Int type because there are things like System.IO.Unsafe.
- mightybyte 13y ago> Even given a simple thing like foo:: int -> int -> int, there's really no way to tell what it's doing. Ahh, this is an important point. The reason you can't tell what it's doing is because it is quite concrete. One really cool thing about this kind of type system is that the more generic your functions, the more you can tell about what it's doing. Consider this function: foo :: (a, b) -> a There's only one possible thing this function can do! And there's only one possible implementation--the correct one. This is the case because the types involved are completely general. Type signatures can communicate a lot more than one might think.
- GeneralMayhem 13y ago>There's only one possible thing this function can do! That's not at all true... it can do all sorts of transformations on the first value of the tuple. I suppose without type restrictions on the parameters it can't do too much because there are relatively few functions defined on all types, but then, how often are you going to see a function signature that vague? More likely, you'd see `foo :: MyClass a => (a, b) -> a` or `foo :: (MyType, b) -> MyType` which opens up the possibilities considerably, because you don't know which of MyType's behaviors is being invoked.
- tel 13y agoThat's exactly it: (a) there are no functions at all defined on all types except id (of type (a -> a)) and (b) you end up seeing signatures close to that vague all the time. This is exactly the power of parametricity.
- eru 13y ago> [...] you end up seeing signatures close to that vague all the time. That's not an accident. Factoring out little helper functions like this is considered a virtue in Haskell (and acording to Paul Graham, also in Lisp). Even if you only use them once---because they make reasoning easier.
- tel 13y agoAgreed! I think the tendency to highly parametric functions comes from several sources. First, good programming practice allows for decomposing entities and leading to more flexible functions. Second, once you have higher kinded types you realize that 90% of programming is wiring between contexts and is more parametric than people think. Finally, HM typing auto generalizes all of your let bindings which means your compiler can inform you of opportunities for genericity that you weren't even aware of... so long as you ask.
- kenferry 13y ago> foo :: (a, b) -> a > There's only one possible thing this function can do! Ah, so it scales a vector by a scalar returning a new vector, right?
- deleted 13y ago[deleted]
- astrobe_ 13y agoIn my mind what I wrote was obviously sarcastic, but apparently it wasn't. Poe's law strikes again I guess.