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 [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners |
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 <[hidden email]> wrote:
_______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners |
In reply to this post by Lawrence Bottorff-2
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! _______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners |
In reply to this post by Lawrence Bottorff-2
On Wed, 23 Dec 2020, Lawrence Bottorff <[hidden email]> wrote: > 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 [hidden email]:/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$ _______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners |
In reply to this post by Lawrence Bottorff-2
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 <[hidden email]> wrote:
_______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners |
Free forum by Nabble | Edit this page |