4 ms·
The points you describe are valid, but there are a few nits: Regarding your first point, your referenced article makes a misstep of its own, conflating the imp
by sharkbot 15y ago
The points you describe are valid, but there are a few nits:
Regarding your first point, your referenced article makes a misstep of its own, conflating the implementation with the semantics. From the article: "Do some folks believe we’re still doing what Church did, i.e., to encode all data as functions and build all types out of ->?"
From a semantics perspective: Yes. If it makes it easier to reason about, then treat variables as nullary functions. In the Spineless, Tagless G-Machine paper, both values and thunks are represented as closures, which may or may not be evaluated. For example:
infiniteSeries :: [Integer]
infiniteSeries = iterate (1+) 1
Is this a variable or a function? Having a special case for Double ("a closure containing a value") versus [Integer] ("a closure containing a thunk") is a distinction only important once the implementation becomes an issue (ie, lazy evaluation affecting memory usage).
As for your second point, typeclasses can include partial implementations. For example, the Eq typeclass [2] has a minimal definition required, either (==) or (/=), as one can be defined in terms of the other.
[1] research.microsoft.com/pubs/67083/spineless-tagless-gmachine.ps.gz
[2] http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Eq http://haskell.org/ghc/docs/latest/html/libraries/base/Prelu...
- ionfish 15y agoGreat points! That we can treat infinite streams as having the same semantics as lists is of course dependent on Haskell's non-strictness—it's not the same in ML, for example. For me one of the more convincing arguments that article puts forward is that Haskell only has unary functions; the type Int -> Int -> Int is just a shorthand for Int -> (Int -> Int), i.e. functions which appear to have more than one argument are considered for the purposes of the semantics to be of the form (λa.(λb.c)). The core point that I think Conal Elliot tries to make is that as far as the denotational semantics is concerned, Haskell has values of many types, some of which (the ones of (abstract) type a -> a) are functions. You are of course correct about Eq and partial implementations. For me the key point is that where one function is defined entirely in terms of other functions and class constraints which ultimately rely on the instance implementing those other functions, they encapsulate the logic of the typeclass—in other words, they define a property of the interface. So equality for values of a given type is ultimately defined by the instance, but the relationship of equality to inequality—a property of the concept of equality in general—is defined by the typeclass.
- masklinn 15y ago> For me one of the more convincing arguments that article puts forward is that Haskell only has unary functions It's not specific to Haskell, you can trivially argue that all languages with functions have only unary functions but most languages use tuples as the function's sole parameter. Haskell even lets you switch a function between the two systems via `curry` and `uncurry`.