Hacker News new | ask | show | jobs
by kittenfluff 3985 days ago
It's not clear to me why it's necessary to include <T, U> at the start of the function definition. In Haskell, unquantified type variables are implicitly universally quantified, i.e. you assume that the signature must be valid for any types T and U.

That's the only thing I think could be substantially improved, though. Personally I find the style where you separate the type signature from the function definition easier to read, for example

How about

    <^> : (T -> U) * T? -> U?
    <^> (f, a) {
        return a.map(f)
    }
or even

    <^> : (T -> U) * T? -> U?
    <^> (f, a) -> a.map(f)
which is already pretty close to the Haskell equivalent

    (<^>) :: (t -> u) -> Maybe t -> Maybe u
    (<^>) = fmap
Arguably, Haskell syntax could be improved with more built-in syntax

    <^> : (t -> u) -> t? -> u?
    <^> = fmap
though I haven't thought about what this means for parsing the language.
3 comments

Explicit is better than implicit. Does Haskell allow functions to have value parameters that aren't declared?
Depends what you mean by "not declared". Haskell doesn't require you to provide type signatures, so if you don't put a type signature on a function, you can have parameters that aren't explicitly declared (though they still have an inferred static type, so you could use ghci to see what all the parameters are). If you do put any type signature on the function, then all parameters would have to be included.
If I make a typo when using a value parameter in a function definition, can I accidentally introduce an extra value parameter?

If I make a typo when using a type parameter in a function definition, can I accidentally introduce an extra type parameter?

> If I make a typo when using a value parameter in a function definition, can I accidentally introduce an extra value parameter?

No.

> If I make a typo when using a type parameter in a function definition, can I accidentally introduce an extra type parameter?

You couldn't introduce a new concrete type. You could introduce a new type variable, but the type signature would still have to typecheck, so it would difficult to come up with a non-contrived example where that would happen.

How do your examples specify that T and U are generics?
As I said, in Haskell "unquantified type variables are implicitly universally quantified" i.e. type variables (which are always lowercase in Haskell, to distinguish them from concrete types which are uppercase) are always generic.

So it's true that in the Swift examples, you would need a convention to distinguish type variables from concrete types, or else you need to explicitly mark them as generic.

Thank you! This actually explained what is going on perfectly.