Given a two-place data constructor, I can partially apply it to one argument then apply that to the second. Why can't I use the same syntax for pattern matching?
data Point = MkPoint Float Float
x = 1.0 :: Float; y = 2.0 :: Float
thisPoint = ((MkPoint x) y) -- partially apply the constructor
(MkPoint x1 y1) = thisPoint -- pattern match OK
((MkPoint x2) y2) = thisPoint -- 'partially apply' the pattern, but rejected: parse error at y2
((MkPoint x3 y3)) = thisPoint -- this accepted, with double-parens
Why do I want to do that? I want to grab the constructor and first arg as an as-pattern, so I can apply it to a different second arg. (Yes the work-round in this example is easy. Realistically I have a much more complex pattern, with several args of which I want to split out the last.):
(mkPx#(MkPoint x4) y4) = thisPoint -- also parse error
thatPoint = mkPx (y4 * 2)
I think there's no fundamental reason to prevent this kind of match.
Certainly it wouldn't do to allow you to write
f (MkPoint x1) = x1
and have that match a partially-applied constructor, i.e. a function. So, one reason to specify it as it was specified here is for simplicity: the RHS of an # has to be a pattern. Simple, easy to parse, easy to understand. (Remember, the very first origins of the language were to serve as a testbed for PL researchers to tinker. Simple and uniform is the word of the day for that purpose.) MkPoint x1 isn't a pattern, therefore mkPx#(MkPoint x1) isn't allowed.
I suspect that if you did the work needed to carefully specify what is and isn't allowed, wrote up a proposal, and volunteered to hack on the parser and desugarer as needed, the GHC folks would be amenable to adding a language extension. Seems like a lot of work for not much benefit, though.
Perhaps record update syntax will scratch your itch with much less effort.
data Point = MkPoint {x, y :: Float}
m#(MkPoint { x = x5 }) = m { x = x5 + 1 }
You also indicate that, aside from the motivation, you wonder what part of the Report says that the pattern you want can't happen. The relevant grammar productions from the Report are here:
pat → lpat
lpat → apat
| gcon apat1 … apatk (arity gcon = k, k ≥ 1)
apat → var [ # apat] (as pattern)
| gcon (arity gcon = 0)
| ( pat ) (parenthesized pattern)
(I have elided some productions that don't really change any of the following discussion.)
Notice that as-patterns must have an apat on their right-hand side. apats are 0-arity constructors (in which case it's not possible to partially apply it) or parenthesized lpats. The lpat production shown above indicates that for constructors of arity k, there must be exactly k apat fields. Since MkPoint has arity 2, MkPoint x is therefore not an lpat, and so (MkPoint x) is not an apat, and so m#(MkPoint x) is not an apat (and so not produced by pat → lpat → apat).
I can partially apply [a constructor] to one argument then apply that to the second.
thisPoint = ((MkPoint x) y) -- partially apply the constructor
There's another way to achieve that without parens, also I can permute the arguments
thisPoint = MkPoint x $ y
thisPoint = flip MkPoint y $ x
Do I expect I could pattern match on that? No, because flip, ($) are just arbitrary functions/operators.
I want to grab the constructor and first arg as an as-pattern, ...
What's special about the first arg? Or the all-but-last arg (since you indicate your real application is more complex)? Do you you expect you could grab the constructor + third and fourth args as an as-pattern?
Haskell's pattern matching wants to keep it simple. If you want a binding to the constructor applied to an arbitrary subset of arguments, use a lambda expression mentioning your previously-bound var(s):
mkPy = \ x5 -> MkPoint x5 y1 -- y1 bound as per your q
Related
I am trying to understand currying by reading various blogs and stack over flow answers and I think I understood some what. In Haskell, every function is curried, it means, when you have a function like f x y = x + y
it really is ((f x) y)
in this, the function initially take the first parameter 'x' as the parameter and partially applies it to function f which in turn returns a function for y. where it takes just y a single parameter and applies the function. In both cases the function takes only one parameter and also the process of reducing a function to take single parameter is called 'currying'. Correct me if my understanding wrong here.
So if it is correct, could you please tell me if the functions 'two' and 'three' are curried functions?
three x y z = x + y + z
two = three 1
same = two 1
In this case, I have two specialized functions, 'two' and 'same' which are reduced to take only one parameter so is it curried?
Let's look at two first.
It has a signature of
two :: Num a => a -> a -> a
forget the Num a for now (it's only a constraint on a - you can read Int here).
Surely this too is a curried function.
The next one is more interesting:
same :: Num a => a -> a
(btw: nice name - it's the same but not exactly id ^^)
TBH: I don't know for sure.
The best definition I know of a curried function is this:
A curried function is a function of N arguments returning another function of (N-1) arguments.
(if you want you can extent this to fully curried functions of course)
This will only fit if you define constants as functions with 0 parameters - which you surely can.
So I would say yes(?) this too is a curried function but only in a mathy borderline way (like the sum of 0 numbers is defined to be 0)
Best just think about this equationally. The following are all equivalent definitions:
f x y z = x+y+z
f x y = \z -> x+y+z
f x = \y -> (\z -> x+y+z)
f = \x -> (\y -> (\z -> x+y+z))
Partial application is only tangentially relevant here. Most often you don't want the actual partial application to be performed and the actual lambda object to be created in memory - hoping instead that the compiler will employ - and optimize better - the full definition at the final point of full application.
The presence of the functions curry/uncurry is yet another confusing issue. Both f (x,y) = ... and f x y = ... are curried in Haskell, of course, but in our heads we tend to think about the first as a function of two arguments, so the functions translating between the two forms are named curry and uncurry, as a mnemonic.
You could think that three function with anonymous functions is:
three = \x -> (\y -> (\z -> x + y + z)))
I am not exactly sure what I am doing wrong. I am stuck and I can't make anymore progress.
I put the error message I get in my code in comment.
If time allows, could someone please check my eval function? I think I am doing something terribly wrong.
Thank you.
Your Let handler will need to extend the environment with the new bindings, and then evaluate the expression with that new environment.
Your environment is a list of name, Value pairs, but the Let contains a list of name, Exp pairs, so you will need to convert the Exps into Values in order to extend the environment. Note that eval converts an Exp into a Value.
However, since the Let can hold multiple bindings, you will need to decide whether the Exps are evaluated in parallel, or sequentially (the difference between let and let* in lisp). Can a binding affect the value of following bindings? Depending upon the answer to that question, you will find yourself using either map or foldl to transform the list.
Your problem with the evaluation of Primitives is twofold. First, you are using a pattern which will only match against a list of exactly one element, but your primitives obviously take different numbers of arguments. The pattern should not use list syntax, since the Primitive constructor guarantees that there will be a list in that position. Instead, you should use a pattern that matches anything (like plain y). Second, the prim function is expecting a list of Values, but the Primitive constructor contains a list of Exp, so you will need to convert them (however, since evaluation of the arguments does not affect the environment, you will be using map).
To get you going in the right direction, in:
eval e (Primitive x [y]) = prim x [eval e y]
the [y] pattern will match only a single element list, with that element bound to y, and [eval e y] is going to result in a single element list. What you want is a pattern that matches the whole list, and then you want to transform that list by applying eval e to each element of that list.
The eval of If also has problems. The condition, the then, and the else are all of type Exp, but eval is supposed to return a Value, so you will have to transform something. Finally, the haskell if wants the condition to be a haskell Bool, but your condition is an Exp. You will need to evaluate the Exp into a Value, and then somehow extract a haskell Bool from the Value. Do you want Number and String Values to behave like Bools in your language (like python), or should only Bool Values behave like Bools?
Finally, finally, if you have any type errors (like trying to Add a String to a Number), or you supply the wrong number of arguments to a primitive, you are going to get a pattern match failure from the prim function (and possibly in the code you will have to write to extract a Bool from your If condition). That may or may not be what you want...
as Thomas M. DuBuisson already said, your let expression has invalid syntax. Second you really have to be aware what type of arguments function takes and what type it returns. You can not mix Exp with Value, for example - where Exp type is expected you have always pass value of Exp type etc.
eval :: Env -> Exp -> Value
-- the return type is Value
-- what are you trying to do here ? extract Value from x ...
eval e (Let [x] y) = eval e $ snd x
-- ... or from y ? Both x & y are of Exp type.
eval e (Let [x] y) = eval e y
There are also more type errors in your code:
eval e (Primitive x [y]) = prim x [y]
-- prim expects 2nd argument of [Value] type so it can be written as
eval e (Primitive x [y]) = prim x [eval e y]
-- dtto, mixing different types is wrong
eval e (If x y z) = if x then y else z
eval e (If x y z) = let Bool x' = eval e x in
if x' then (eval e y) else (eval e z)
and finally main expects IO () as the return type so you have to reflect this somehow, like printing the eval result:
print $ eval [("y", (Number 40))] (Let [("x", (Literal (Number 2)))] (Primitive Add [(Variable "x"), (Variable "y")]))
You want something like
let e' = {- extend env with x -} in eval e' y
I've been asking a few questions about strictness, but I think I've missed the mark before. Hopefully this is more precise.
Lets say we have:
n = 1000000
f z = foldl' (\(x1, x2) y -> (x1 + y, y - x2)) z [1..n]
Without changing f, what should I set
z = ...
So that f z does not overflow the stack? (i.e. runs in constant space regardless of the size of n)
Its okay if the answer requires GHC extensions.
My first thought is to define:
g (a1, a2) = (!a1, !a2)
and then
z = g (0, 0)
But I don't think g is valid Haskell.
So your strict foldl' is only going to evaluate the result of your lambda at each step of the fold to Weak Head Normal Form, i.e. it is only strict in the outermost constructor. Thus the tuple will be evaluated, however those additions inside the tuple may build up as thunks. This in-depth answer actually seems to address your exact situation here.
W/R/T your g: You are thinking of BangPatterns extension, which would look like
g (!a1, !a2) = (a1, a2)
and which evaluates a1 and a2 to WHNF before returning them in the tuple.
What you want to be concerned about is not your initial accumulator, but rather your lambda expression. This would be a nice solution:
f z = foldl' (\(!x1, !x2) y -> (x1 + y, y - x2)) z [1..n]
EDIT: After noticing your other questions I see I didn't read this one very carefully. Your goal is to have "strict data" so to speak. Your other option, then, is to make a new tuple type that has strictness tags on its fields:
data Tuple a b = Tuple !a !b
Then when you pattern match on Tuple a b, a and b will be evaluated.
You'll need to change your function regardless.
There is nothing you can do without changing f. If f were overloaded in the type of the pair you could use strict pairs, but as it stands you're locked in to what f does. There's some small hope that the compiler (strictness analysis and transformations) can avoid the stack growth, but nothing you can count on.
How does CPS in curried languages like lambda calculus or Ocaml even make sense? Technically, all function have one argument. So say we have a CPS version of addition in one such language:
cps-add k n m = k ((+) n m)
And we call it like
(cps-add random-continuation 1 2)
This is then the same as:
(((cps-add random-continuation) 1) 2)
I already see two calls there that aren't tail calls and in reality a complexly nested expression, the (cps-add random-continuation) returns a value, namely a function that consumes a number, and then returns a function which consumes another number and then delivers the sum of both to that random-continuation. But we can't work around this value returning by simply translating this into CPS again, because we can only give each function one argument. We need to have at least two to make room for the continuation and the 'actual' argument.
Or am I missing something completely?
Since you've tagged this with Haskell, I'll answer in that regard: In Haskell, the equivalent of doing a CPS transform is working in the Cont monad, which transforms a value x into a higher-order function that takes one argument and applies it to x.
So, to start with, here's 1 + 2 in regular Haskell: (1 + 2) And here it is in the continuation monad:
contAdd x y = do x' <- x
y' <- y
return $ x' + y'
...not terribly informative. To see what's going on, let's disassemble the monad. First, removing the do notation:
contAdd x y = x >>= (\x' -> y >>= (\y' -> return $ x' + y'))
The return function lifts a value into the monad, and in this case is implemented as \x k -> k x, or using an infix operator section as \x -> ($ x).
contAdd x y = x >>= (\x' -> y >>= (\y' -> ($ x' + y')))
The (>>=) operator (read "bind") chains together computations in the monad, and in this case is implemented as \m f k -> m (\x -> f x k). Changing the bind function to prefix form and substituting in the lambda, plus some renaming for clarity:
contAdd x y = (\m1 f1 k1 -> m1 (\a1 -> f1 a1 k1)) x (\x' -> (\m2 f2 k2 -> m2 (\a2 -> f2 a2 k2)) y (\y' -> ($ x' + y')))
Reducing some function applications:
contAdd x y = (\k1 -> x (\a1 -> (\x' -> (\k2 -> y (\a2 -> (\y' -> ($ x' + y')) a2 k2))) a1 k1))
contAdd x y = (\k1 -> x (\a1 -> y (\a2 -> ($ a1 + a2) k1)))
And a bit of final rearranging and renaming:
contAdd x y = \k -> x (\x' -> y (\y' -> k $ x' + y'))
In other words: The arguments to the function have been changed from numbers, into functions that take a number and return the final result of the entire expression, just as you'd expect.
Edit: A commenter points out that contAdd itself still takes two arguments in curried style. This is sensible because it doesn't use the continuation directly, but not necessary. To do otherwise, you'd need to first break the function apart between the arguments:
contAdd x = x >>= (\x' -> return (\y -> y >>= (\y' -> return $ x' + y')))
And then use it like this:
foo = do f <- contAdd (return 1)
r <- f (return 2)
return r
Note that this is really no different from the earlier version; it's simply packaging the result of each partial application as taking a continuation, not just the final result. Since functions are first-class values, there's no significant difference between a CPS expression holding a number vs. one holding a function.
Keep in mind that I'm writing things out in very verbose fashion here to make explicit all the steps where something is in continuation-passing style.
Addendum: You may notice that the final expression looks very similar to the de-sugared version of the monadic expression. This is not a coincidence, as the inward-nesting nature of monadic expressions that lets them change the structure of the computation based on previous values is closely related to continuation-passing style; in both cases, you have in some sense reified a notion of causality.
Short answer : of course it makes sense, you can apply a CPS-transform directly, you will only have lots of cruft because each argument will have, as you noticed, its own attached continuation
In your example, I will consider that there is a +(x,y) uncurried primitive, and that you're asking what is the translation of
let add x y = +(x,y)
(This add faithfully represent OCaml's (+) operator)
add is syntaxically equivalent to
let add = fun x -> (fun y -> +(x, y))
So you apply a CPS transform¹ and get
let add_cps = fun x kx -> kx (fun y ky -> ky +(x,y))
If you want a translated code that looks more like something you could have willingly written, you can devise a finer transformation that actually considers known-arity function as non-curried functions, and tream all parameters as a whole (as you have in non-curried languages, and as functional compilers already do for obvious performance reasons).
¹: I wrote "a CPS transform" because there is no "one true CPS translation". Different translations have been devised, producing more or less continuation-related garbage. The formal CPS translations are usually defined directly on lambda-calculus, so I suppose you're having a less formal, more hand-made CPS transform in mind.
The good properties of CPS (as a style that program respect, and not a specific transformation into this style) are that the order of evaluation is completely explicit, and that all calls are tail-calls. As long as you respect those, you're relatively free in what you can do. Handling curryfied functions specifically is thus perfectly fine.
Remark : Your (cps-add k 1 2) version can also be considered tail-recursive if you assume the compiler detect and optimize that cps-add actually always take 3 arguments, and don't build intermediate closures. That may seem far-fetched, but it's the exact same assumption we use when reasoning about tail-calls in non-CPS programs, in those languages.
yes, technically all functions can be decomposed into functions with one method, however, when you want to use CPS the only thing you are doing is saying is that at a certain point of computation, run the continuation method.
Using your example, lets have a look. To make things a little easier, let's deconstruct cps-add into its normal form where it is a function only taking one argument.
(cps-add k) -> n -> m = k ((+) n m)
Note at this point that the continuation, k, is not being evaluated (Could this be the point of confusion for you?).
Here we have a method called cps-add k that receives a function as an argument and then returns a function that takes another argument, n.
((cps-add k) n) -> m = k ((+) n m)
Now we have a function that takes an argument, m.
So I suppose what I am trying to point out is that currying does not get in the way of CPS style programming. Hope that helps in some way.
I'm trying to convert a point in cartesian 3d coordinate system to a spherical 3d system.
This is what I got so far:
radialDistance3D (x,y,z) = sqrt (x*2 + y*y + z*z)
cartesian3DToPolar3D (x,y,z) = (r,alpha, beta)
where r = radialDistance3D (x,y,z)
alpha = acos(z/r)
beta = atan2(y,x)
Ghci loads the code but when I try to execute it with
cartesian3DToPolar3D (1.0,2.0,3.0)
I get:
<interactive>:1:0:
No instance for (RealFloat (t, t))
arising from a use of `cartesian3DToPolar3D'
at <interactive>:1:0-33
Possible fix: add an instance declaration for (RealFloat (t, t))
In the expression: cartesian3DToPolar3D (1.0, 2.0, 3.0)
In the definition of `it':
it = cartesian3DToPolar3D (1.0, 2.0, 3.0)
Which isn't helpfull. What is going on?
Conversion formulas are from http://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates
More generally, in Haskell arguments are not normally written in the form "foo (x,y,z)". Instead we write "foo x y z". The former is legal: it wraps up the arguments into a single value (known as a tuple) and passes that, but its unnecessary.
The error message came from the line
beta = atan2 (y, x).
This failed because of the type of the library function atan2, which is roughly
atan2 :: RealFloat a => a -> a -> a
This means that for any type "a" which is an instance of "RealFloat" (i.e. the types "Float" and "Double"), the function "atan2" takes two of them as arguments and returns a new one. The "RealFloat a => ..." bit says that in the rest of the type "a" can be any type which is declared to be an instance of the class RealFloat. "Float" and "Double" are examples of these types. So one potential type for this function is:
atan2 :: Double -> Double -> Double
However what you did was treat it as though it had a different type:
atan2 :: (Double, Double) -> Double
This says that "atan2" takes a single argument which is a tuple containing two values. The type checker tried to see if this whole tuple is an instance of "RealFloat" (i.e. one of the types that we can substitute for "a" in the type of "atan2"), and found that it isn't. So it generated an error message saying so.
What is actually going on in the "atan2 y x" syntax, and in the arrows in the type signature, is revealed when you put the implicit brackets back in. The "->" type operator is right associative, so the type of atan2 is actually:
atan2 :: Double -> (Double -> Double)
(Note: for simplicity I'm leaving out the "RealFloat a" business.) This says that "atan2" takes an argument and returns a new function which expects the second argument.
Now lets put the implicit brackets into the call. Function application is left associative, so the definition of "beta" looks like this;
beta = (atan2 x) y
Following the rule of evaluating brackets from the inside out, this applies the function "atan2" to "x" and gets a new function as a result, which is then applied to "y" giving "beta" as a result. See how the type and the expression mirror each other?
This is not just a theoretical trick: I could write something like
myBeta = atan2 x
...
beta = myBeta y
Or even
betas = map myBeta ys
where "ys" and "betas" are lists of values. Being able to do something like this is one of the great strengths of Haskell.
Corrected code:
radialDistance3D (x,y,z) = sqrt (x*x + y*y + z*z)
cartesian3DToPolar3D (x,y,z) = (r,alpha, beta)
where r = radialDistance3D (x,y,z)
alpha = acos(z/r)
beta = atan2 y x
There were two mistakes, first was in
radialDistance3D (x,y,z) = sqrt (x*2 + y*y + z*z)`
which should be
radialDistance3D (x,y,z) = sqrt (x*x + y*y + z*z)
the second was
beta = atan2(y,x)
which should be
beta = atan2 x y