
I have these three versions of addition addA x y = x + y addB x = \y -> x + y addC = \x -> \y -> x + y and all three add two arguments just fine
addA 2 3 5 addB 2 3 5 addC 2 3 5
but I can't see how addB and addC are actually accomplishing this. addA is currying, which I don't fully follow. addC I understand beta reduction-wise (\x -> \y -> x + y) 2 3 (\y -> 2 + y) 3 (2 + 3) 5 but I don't understand addB and what steps are happening currying/beta reduction-wise. Can someone break down the steps with addA and addB? LB

The steps and semantics are the same, the only meaningful difference is
syntax.
These two definitions are indistinguishable:
f x = y
f = \x -> y
In basically the same way that these two expressions are:
(+) 1 2
1 + 2
In Haskell there are many cases where a more convenient but equivalent
syntax exists to express certain terms. This is referred to as syntax sugar.
On Wed, Dec 23, 2020 at 19:12 Lawrence Bottorff
I have these three versions of addition
addA x y = x + y addB x = \y -> x + y addC = \x -> \y -> x + y
and all three add two arguments just fine
addA 2 3 5 addB 2 3 5 addC 2 3 5
but I can't see how addB and addC are actually accomplishing this. addA is currying, which I don't fully follow. addC I understand beta reduction-wise
(\x -> \y -> x + y) 2 3 (\y -> 2 + y) 3 (2 + 3) 5
but I don't understand addB and what steps are happening currying/beta reduction-wise. Can someone break down the steps with addA and addB?
LB
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Il 23 dicembre 2020 alle 21:12 Lawrence Bottorff ha scritto:
I have these three versions of addition
addA x y = x + y addB x = \y -> x + y addC = \x -> \y -> x + y
[…]
I can't see how addB and addC are actually accomplishing this. addA is currying, which I don't fully follow.
Parameters on the left-hand side of a function definition can always be expressed as a lambda, by «plucking» them from the rightmost one addA x y = x + y addA x = \y -> x + y addA = \x -> \y -> x + y -- those three are equal! Intuitively you can say that first we are binding the patterns in the function definition and then the one left in the lambda right-hand side (if any). So: add 3 5 addA x = \y -> x + y 3 5 \y -> 3 + y 5 3 + 5 I suspect what the book is trying to teach you is that you can partially apply a function and pass it around merrily: map (addA 3) [1, 2, 3] So by writing `addA 3` we obtain: addA :: Int -> Int -> Int addA :: Int -> (Int -> Int) -- can also be written like this -- since `(->)` is associates to -- the right add3 :: Int -> Int -- applying addA to 3 another function with one parameter less. Once everything is applied, you will get your result!

On Wed, 23 Dec 2020, Lawrence Bottorff
I have these three versions of addition
addA x y = x + y addB x = \y -> x + y addC = \x -> \y -> x + y
and all three add two arguments just fine
addA 2 3 5 addB 2 3 5 addC 2 3 5
but I can't see how addB and addC are actually accomplishing this. addA is currying, which I don't fully follow. addC I understand beta reduction-wise
(\x -> \y -> x + y) 2 3 (\y -> 2 + y) 3 (2 + 3) 5
but I don't understand addB and what steps are happening currying/beta reduction-wise. Can someone break down the steps with addA and addB?
LB
Dear Lawrence Bottorf, your questions are delightful! Heaven forwarding, I will respond more fully and clearly. The questions you ask strike at the heart of the issue: Why is Haskell so hard to learn? I offer no decent answer here, but I give below a transcript of an incoherent session with ghci on panix3.panix.com, panix3% ghci --version The Glorious Glasgow Haskell Compilation System, version 7.8.4 panix3% uname -a NetBSD panix3.panix.com 9.0 NetBSD 9.0 (PANIX-XEN-USER) #1: Sun May 3 21:15:18 EDT 2020 root@juggler.panix.com:/misc/obj64/misc/devel/netbsd/9.0/src/sys/arch/amd64/compile/PANIX-XEN-USER amd64 panix3% Below is the whole transcript of the session. Note two things: 1. I do not know ghci. 2. I failed to ask the ':t" questions in the right order, for a good training video. But I hope the transcript is helpful. oo--JS. bash-5.0$ ghci GHCi, version 7.8.4: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Prelude> let addA x y = x + y Prelude> addA <interactive>:6:1: No instance for (Show (a0 -> a0 -> a0)) arising from a use of `print' In a stmt of an interactive GHCi command: print it Prelude> print addA <interactive>:7:1: No instance for (Show (a0 -> a0 -> a0)) arising from a use of `print' In the expression: print addA In an equation for `it': it = print addA <interactive>:7:7: No instance for (Num a0) arising from a use of `addA' The type variable `a0' is ambiguous Note: there are several potential instances: instance Num Double -- Defined in `GHC.Float' instance Num Float -- Defined in `GHC.Float' instance Integral a => Num (GHC.Real.Ratio a) -- Defined in `GHC.Real' ...plus three others In the first argument of `print', namely `addA' In the expression: print addA In an equation for `it': it = print addA Prelude> let addA x y = x + y Prelude> print it <interactive>:9:7: Not in scope: `it' Perhaps you meant `id' (imported from Prelude) Prelude> addA <interactive>:10:1: No instance for (Show (a0 -> a0 -> a0)) arising from a use of `print' In a stmt of an interactive GHCi command: print it Prelude> addA 7 <interactive>:11:1: No instance for (Show (a0 -> a0)) arising from a use of `print' In a stmt of an interactive GHCi command: print it Prelude> addA 7 5 12 Prelude> (addA 7) <interactive>:13:1: No instance for (Show (a0 -> a0)) arising from a use of `print' In a stmt of an interactive GHCi command: print it Prelude> :t (addA 7) (addA 7) :: Num a => a -> a Prelude> :t addA addA :: Num a => a -> a -> a Prelude> :t addA 7 addA 7 :: Num a => a -> a Prelude> :t addA 7 5 addA 7 5 :: Num a => a Prelude> let addB x = \y -> x + y Prelude> :t addB addB :: Num a => a -> a -> a Prelude> :t addB 7 addB 7 :: Num a => a -> a Prelude> :t (addB 7) (addB 7) :: Num a => a -> a Prelude> :t addB 7 5 addB 7 5 :: Num a => a Prelude> let addC = \x -> \y -> x + y Prelude> :t addC addC :: Num a => a -> a -> a Prelude> :t (addC) (addC) :: Num a => a -> a -> a Prelude> :t addC 7 addC 7 :: Num a => a -> a Prelude> :t (addC 7) (addC 7) :: Num a => a -> a Prelude> :t addC 7 5 addC 7 5 :: Num a => a Prelude> addC 7 5 12 Prelude> (addC 7 5) 12 Prelude> (exit) <interactive>:31:2: Not in scope: `exit' Prelude> Leaving GHCi. bash-5.0$

Hi, Lawrence,
Would it help you to think of addB as a function that takes its argument x
and returns a function/lambda that adds x to the argument to which that
returned function is applied?
Best wishes,
-jn-
On Wed, Dec 23, 2020 at 9:12 PM Lawrence Bottorff
I have these three versions of addition
addA x y = x + y addB x = \y -> x + y addC = \x -> \y -> x + y
and all three add two arguments just fine
addA 2 3 5 addB 2 3 5 addC 2 3 5
but I can't see how addB and addC are actually accomplishing this. addA is currying, which I don't fully follow. addC I understand beta reduction-wise
(\x -> \y -> x + y) 2 3 (\y -> 2 + y) 3 (2 + 3) 5
but I don't understand addB and what steps are happening currying/beta reduction-wise. Can someone break down the steps with addA and addB?
LB
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
participants (5)
-
Bob Ippolito
-
Francesco Ariis
-
Jay Sulzberger
-
Joel Neely
-
Lawrence Bottorff