Meeting 1

Meeting text

(16:00) SethTisue: it's 5:00, let's start
(16:00) JoshUnterman: agreed.
(16:01) JoshUnterman: so, i thought that last exercise was lame
(16:01) hellige: MEETING TIME
(16:01) Oliver_Gugenheim: here!
(16:01) MarkoKrema: here
(16:01) haskelletor: here
(16:01) JoshUnterman: here here!
(16:02) kreig: here
(16:02) actuallyforrest: here
(16:02) kreig: 5?
(16:02) JoshUnterman: you're late
(16:02) sandover: sorry aboot that
(16:02) JoshUnterman: mm hmm
(16:02) sandover: (i get a canadian accent when i'm feeling apologetic)
(16:02) JoshUnterman: understandab;e
(16:02) JoshUnterman: but yeah
(16:02) Oliver_Gugenheim: first class introduction:
(16:03) hellige: i'm matt
(16:03) JoshUnterman: i thought that last exercise was lame. i don't think they gave us enough to do it. without using last in order to handle the small list cases
(16:03) haskelletor: josh is getting uppity
(16:03) Oliver_Gugenheim: which problem do you mean?
(16:04) JoshUnterman: the second-to-last element of a list problem
(16:04) hellige: i did it a different way, i guess, but i think you could do it
(16:04) hellige: using just what they provide
(16:04) kreig: are you talking about lastButOne?
(16:04) JoshUnterman: yeah
(16:05) kreig: I have two implementations that handle short lists
(16:05) JoshUnterman: bring em on
(16:05) Oliver_Gugenheim: the problem was a bit under-specified
(16:05) hellige: well, what do you mean by "handle" short lists?
(16:05) MarkoKrema: I Know Matt from work, Seth from school, and Josh from SF
(16:05) Oliver_Gugenheim: what was the desired behavior on one and zero element lists?
(16:05) kreig: > 2 + 2
(16:05) hrgbot: fd:12: hClose: resource vanished (Broken pipe)
(16:06) haskelletor: who is that bogus bot?
(16:06) Oliver_Gugenheim: so, should we talk about chapter one?
(16:06) MarkoKrema: I know lisp and perl and c#
(16:06) Oliver_Gugenheim: or skip ahead to chap 2 and talk about various solutions to problem 2?
(16:06) kreig: yah, chapter 1!
(16:07) SethTisue: if anyone has a chapter one thing they can raise it
(16:07) JoshUnterman: i didn't have many thoughts on chapter 1.
(16:07) kreig: well, I got a nie emacs env set u
(16:07) kreig: under OSX
(16:07) Oliver_Gugenheim: I didn't really understand the types of succ 6
(16:07) hellige: :)
(16:07) Oliver_Gugenheim: and pred 9
(16:07) Oliver_Gugenheim: and all that nonsense
(16:08) Oliver_Gugenheim: (Enum t, Num t) => t
(16:08) hellige: what was confusing about it?
(16:08) Oliver_Gugenheim: what's an Enum?
(16:08) hellige: oh, you shouldn't have gotten types like that…
(16:08) Oliver_Gugenheim: d'oh
(16:08) hellige: that will make things FAR more confusing
(16:08) hellige: for now.
(16:08) hellige: i think i see what happened.
(16:08) hellige: no, it
(16:08) hellige: it's their fault…
(16:08) hellige: if you use :set +t
(16:09) SethTisue: I found it confusing that ":type 6" is (Num t) but if I type "6" then ":type it" I get Int
(16:09) hellige: and then just type the epxressions…
(16:09) hellige: SethTisue: yes, that's exactly the problem
(16:09) SethTisue: but I sort of assumed it would be clear later
(16:09) hellige: it will
(16:09) hellige: or i can make it clear now
(16:09) hellige: it's up to you guys
(16:09) kreig: I know why 8)
(16:09) Oliver_Gugenheim: what does :set +t do?
(16:09) MarkoKrema: I have a question about this ghci interaction:
(16:09) kreig: you are asking it the value of an expression
(16:09) MarkoKrema: Prelude> let x=1
(16:09) MarkoKrema: Prelude> :show bindings
(16:09) MarkoKrema: it :: Double = 1.0
(16:09) MarkoKrema: x :: Integer =
(16:09) hellige: Oliver_Gugenheim: that makes it print the type of "it" after each expression.
(16:10) MarkoKrema: why is x Integer=_?
(16:10) hellige: MarkoKrema: let's finish with the types question first
(16:10) hellige: then we'll get to that.
(16:10) MarkoKrema: ok
(16:10) Oliver_Gugenheim: what was confusing
(16:10) Oliver_Gugenheim: was that doing ":type sqrt 16"
(16:10) SethTisue: Hellige: I'd be interested in hearing a short answer now without going off on a long tangent about it
(16:10) Oliver_Gugenheim: did what I expected
(16:11) Oliver_Gugenheim: but not for pred
(16:11) hellige: ok, i'll explain quickly.
(16:11) hellige: Oliver_Gugenheim: this will explain your question too.
(16:11) gregfast: there was homework? i guess i also did it wrong then
(16:11) Oliver_Gugenheim: sorry, we can skip if everyone else is bored
(16:11) hellige: to understand numbers in haskell, we have to know a little about type classes
(16:12) JoshUnterman: we need a conch shell
(16:12) hellige: i won't get into it in depth, but basically type classes are a way to allow overloading of functions
(16:12) hellige: so that you can define a function like (==), which checks equality, but has a different implementation for different types.
(16:13) hellige: now, haskell does not do any automatic coercion, so you can't use an integer where a double is needed.
(16:13) hellige: but we know that you can do stuff like:
(16:13) hellige: 2 :: Double
(16:13) hellige: and 2 :: Integer
(16:13) hellige: and it will work.
(16:13) hellige: how does this work, without coercion?
(16:13) hellige: the answer is: haskell has a type class Num for numbers.
(16:13) hellige: numeric literals are NOT integers
(16:14) hellige: they are values that can take ANY type as long as that type is an instance of Num
(16:14) hellige: this is why, technically:
(16:14) hellige: 5 :: (Num t) => t
(16:14) hellige: this means 5 can have any type t if t is a Num
(16:15) sandover: but how can something be a Num and also be an Integer?
(16:15) SethTisue: ok thanks
(16:15) hellige: now, some functions PRESERVE this generality, they will work with any num
(16:15) FrankDuncan: How is that not casting?
(16:15) hellige: but some RESTRICT it.
(16:15) hellige: sqrt works only for doubles
(16:15) Oliver_Gugenheim: so, it's like Num<T> in Java?
(16:15) Oliver_Gugenheim: somewhat …
(16:15) hellige: so "sqrt 6" forces 6 to be a double, and then returns a double
(16:16) hellige: but pred and succ can work with any Num (well, any Num that is also an Enum, but that's getting too complicated…)
(16:16) SethTisue: so if I say ":type sqrt 16" I'm not saying "compute the answer and tell me what type it is", I'm asking "what does the type inferencer say about what the type of the answer will be?"
(16:16) gregfast: it's kinda like type casting, if you could only cast to interfaces
(16:16) FrankDuncan: So the reader reads in 6 and initially makes it a Num, but you then specify that to be a Double?
(16:16) hellige: SethTisue: YES
(16:16) FrankDuncan: Ok.
(16:16) hellige: FrankDuncan: sort of
(16:16) hellige: that's a good enough understanding for now.
(16:17) Oliver_Gugenheim: ok
(16:17) hellige: this is a really poweful feature, incidentally
(16:17) FrankDuncan: hellige: Ok, how long will it be preserved as a Num before becoming a Double?
(16:17) Oliver_Gugenheim: thanks
(16:17) FrankDuncan: Just until I use it?
(16:17) hellige: it means that you can write new number types (like complex numbers) and regular numeric literals will work.
(16:17) hellige: which is pretty cool.
(16:17) hellige: FrankDuncan: until it's forced to be something else
(16:17) hellige: that's why "succ 6" is still a really general type
(16:17) FrankDuncan: hellige: So a function written against Num will still not coerce it one way or the other?
(16:17) FrankDuncan: hellige: Ha, way to answer before.
(16:18) hellige: but it's tricky in ghci, because the interpreter will force an arbitrary num to something specific.
(16:18) sandover: (shortcut: you can do :t instead of :type)
(16:18) hellige: that's why you get a different answer if you do ":t 5"
(16:18) hellige: or
(16:18) hellige: 5
(16:18) hellige: :t it
(16:19) sandover: hellige: could you explain the syntax of: 5 :: (Num t) => t
(16:19) hellige: incidentally, it's very unfortunate that you had to deal with this in chapter 1. i know the authors made efforts to hide type classes for a few chapters.
(16:19) hellige: yeah
(16:20) kreig: 5 isa type t, which is a Num
(16:20) hellige: sandover: a type like (Num t) => t is a qualified type
(16:20) hellige: what kreig said
(16:20) hellige: the actual type is after the =>
(16:20) sandover: what is this => arrow
(16:20) hellige: so t is just a type variable
(16:20) kreig: t is a variable, which stands for any type
(16:20) hellige: the => introduces constraints.
(16:20) JoshUnterman: let's move on. i think they're going to cover this more later.
(16:20) JoshUnterman: although i appreciate what's been said so far
(16:20) kreig: don't be so sure 8)
(16:21) JoshUnterman: heh
(16:21) hellige: :)
(16:21) SethTisue: anyone else have chapter 1 stuff?
(16:21) hellige: ok, oliver, are you happy enough with that for now?
(16:21) FrankDuncan: Wait, => intorduces constraints?
(16:21) Oliver_Gugenheim: sure
(16:21) FrankDuncan: That confused me.
(16:21) hellige: FrankDuncan: constraints come before the =>
(16:21) FrankDuncan: But if that's answered later, I'll wait :)
(16:21) hellige: so (Num t) => t
(16:21) FrankDuncan: I thought => had to do with types returned or something
(16:22) hellige: no, that is ->
(16:22) SethTisue: that's ->
(16:22) FrankDuncan: Ooohh
(16:22) FrankDuncan: Argh!
(16:22) SethTisue: anyone else have chapter 1 stuff?
(16:22) JoshUnterman: yeah. that shit's annoying. but whatever. i'm with frank. as long as => is covered a bit later on, i'm good to move to chapter 2.
(16:22) hellige: FrankDuncan: here is an example
(16:22) kreig: haskell has cons
(16:23) hellige: (+) :: (Num a) => a -> a -> a
(16:23) SethTisue: oh here's a chapter 1 thing
(16:23) SethTisue: is there only solution to the last exercise?
(16:23) SethTisue: only one solution?
(16:23) haskelletor: so it's basically saying you've got a type variable that's constrained to be a Num
(16:23) haskelletor: a is Num
(16:23) hellige: haskelletor: yes
(16:24) hellige: SethTisue: the number of characters in a file?
(16:24) Oliver_Gugenheim: but why isn't plus defined as
(16:24) JoshUnterman: the way i did the last exercise in chapter 1 was to use length.(16:24) SethTisue: "Modify the WC.hs example again, to print the number of characters in a file."
(16:24) Oliver_Gugenheim: (+) :: (Num a) => a, a -> a
(16:24) hellige: Oliver_Gugenheim: because it is "curried". i insist that we defer this question. :)
(16:24) Oliver_Gugenheim: :(
(16:24) haskelletor: ah yeah curried
(16:24) Oliver_Gugenheim: ok
(16:25) hellige: SethTisue: i came up with one solution. i'm sure there are others. why do you ask?
(16:25) Oliver_Gugenheim: silly chapter 1
(16:25) SethTisue: oh right, length. kind of a trick question because it's simpler than what they've already shown you, not harder
(16:25) JoshUnterman: (length (lines input))
(16:25) Oliver_Gugenheim: (length input)
(16:25) SethTisue: no other solutions using what we've been shown, I mean
(16:25) JoshUnterman: yeah. i didn't particularly like that exercise, but they admitted upfront that it was kinda lame.
(16:25) hellige: Oliver_Gugenheim: yeah that's how i did it
(16:25) hellige: it was a lame exercise
(16:26) hellige: but chapter 1 was kind of a slog
(16:26) SethTisue: ok that was what I was checking :-)
(16:26) kreig: get rid o the lines call
(16:26) SethTisue: chapter 2, then
(16:26) hellige: wait
(16:26) Oliver_Gugenheim: it seemed strange to make the first exercise have to do with i/o
(16:26) hellige: marko had a question
(16:26) kreig: hold on 8)
(16:26) SethTisue: Josh, there is a recursive solution to lastButOne
(16:26) kreig: the : operator
(16:26) hellige: marko had a good question
(16:26) SethTisue: oh sorry
(16:26) kreig: yummy, list comprehension
(16:26) MarkoKrema: oh, I thought it was a bad question
(16:26) JoshUnterman: i did a recursive solution. but hwat's the base case
(16:26) hellige: MarkoKrema: no way
(16:26) hellige: good question
(16:26) hellige: what was it again?
(16:26) Oliver_Gugenheim: are we on chapter 2?
(16:27) Oliver_Gugenheim: or still talking about counting characters/words/lines?
(16:27) MarkoKrema: Prelude> let x=1
(16:27) MarkoKrema: Prelude> :show bindings
(16:27) MarkoKrema: it :: Double = 1.0
(16:27) MarkoKrema: x :: Integer =
(16:27) MarkoKrema: Why Iteger=_
(16:27) hellige: oh right
(16:27) hellige: anybody?
(16:27) Oliver_Gugenheim: oh yeah
(16:27) Oliver_Gugenheim: that was confusing too
(16:27) Oliver_Gugenheim: but when I redefined x
(16:27) Oliver_Gugenheim: I got Integer = 1
(16:28) hellige: really?
(16:28) sandover: me too
(16:28) Oliver_Gugenheim: truly
(16:28) hellige: oh wait
(16:28) hellige: did you evaluate it?
(16:28) hellige: like
(16:28) hellige: let x = 1
(16:28) hellige: x
(16:28) MarkoKrema: me too
(16:28) hellige: :show bindigns
(16:28) kreig: lazy evaluation
(16:28) FrankDuncan: I think it evaluates it in order to print it.
(16:29) kreig: it has't used the expression yet
(16:29) kreig: let y=2
(16:29) MarkoKrema: ah!
(16:29) kreig: :show bindings
(16:29) sandover: wait, i get a different result for that if i start ghci fresh.
(16:29) kreig: then do y + 2
(16:29) Oliver_Gugenheim: oh man
(16:29) kreig: and then do :show bindings
(16:29) SethTisue: cool
(16:29) hellige: kreig: it always keeps the _ for me.
(16:29) Oliver_Gugenheim: it's Heisenberg at work
(16:29) hellige: but yeah, that's the answer in any case
(16:29) kreig: here is what I just did
(16:29) ChrisKeating: so _ always means unevaluated expression?
(16:29) kreig: with a fresh ghci (or fresh var)
(16:30) sandover: starting from zero, doing let x = 1 and then show bindings give a one-line response: x :: Integer =
(16:30) MarkoKrema: thx. I gotta go unfortunately. Chad or Matt or Brandon, save me the buffer. See you next week!
(16:30) sandover: yes, it hasn't been evaulated yet
(16:30) haskelletor: is this thunkz already?
(16:30) sandover: it could be let x = 1/0
(16:30) sandover: and that would be OK.
(16:30) FrankDuncan: Btw, all, I'm collectin ghte buffer and will put it on the wiki
(16:30) ChrisKeating: wasn't someone going to log this?
(16:30) haskelletor: bone thunkz
(16:31) hellige: hahahahahaha
(16:31) hellige: bone thunkz and harmony
(16:31) kreig: this is thunkz already
(16:31) hellige: yeah
(16:31) haskelletor: i love that they don't front on the thunks
(16:31) hellige: so here is why you would care
(16:31) FrankDuncan: hellige: I'm missing why it inferred the type of y to Integer instead of keeping it Num?
(16:31) haskelletor: it's like chapter 2.. bam!
(16:31) hellige: let xs = [1..]
(16:32) hellige: :show bindings
(16:32) hellige: it would be sort of lame if it tried to print that infinite list.
(16:32) JoshUnterman: so if we now > let x = 2, :show bindings still has x bound to 1
(16:32) kreig: yah, me too
(16:32) FrankDuncan: hellige: No no, I don't mean the _, I get that.
(16:32) sandover: single assignment, baby
(16:32) kreig: typing it as Integer instead of Num
(16:32) JoshUnterman: yeah. funny that it didn't throw an error or anything though
(16:33) Oliver_Gugenheim: but I don't understand the single assignment
(16:33) sandover: actually, maybe ghci is not single assignment
(16:33) Oliver_Gugenheim: since it treats x as having a different value
(16:33) sandover: i just reassigned x
(16:33) hellige: sandover: no you didn't, now treally
(16:33) Oliver_Gugenheim: but shows the first assigned value in show bindings
(16:33) kreig: ghci is special
(16:33) hellige: you shadowed it.
(16:33) Oliver_Gugenheim: sigh
(16:33) Oliver_Gugenheim: ok
(16:33) hellige: here is the difference
(16:33) Oliver_Gugenheim: that's just some crazy interpreter thing
(16:33) Oliver_Gugenheim: ?
(16:33) hellige: no
(16:34) hellige: actually it's not
(16:34) hellige: it seems like it, but it's actually not, which is kinda cool
(16:34) hellige: but first…
(16:34) JoshUnterman: so now, after let x = 2, x evaluates to 2, but show bindings shows x being 1
(16:34) hellige: here is the difference between shadowing and re-assigning
(16:34) FrankDuncan: Yay for shadowing :)
(16:34) kreig: Frank: I think it infers the type to Integer
(16:34) FrankDuncan: kreig: Yeah, matt just talked ot me in PMs about it, it's another crazy interpreter thing.
(16:35) hellige: let x = 1
(16:35) hellige: let f = \_ -> x
(16:35) kreig: Frank: because it knows the expression is of type Integer
(16:35) hellige: let x = 2
(16:35) hellige: f ()
(16:35) sandover: is that lamba function non-pure? seems to rely on a "global variable"
(16:35) kreig: like when you do :type 2
(16:35) hellige: sandover: it's pure, because x can't vary
(16:36) kreig: vs :type it (when it is 2)
(16:36) sandover: unless it's re-bound! that's a sneaky sneak.
(16:36) hellige: sandover: no
(16:36) FrankDuncan: hellige: Does "let =" define a new let block for the rest of the interactive session?
(16:36) hellige: the last line will still print 1
(16:36) SethTisue: Frank: YES
(16:36) hellige: FrankDuncan: effectively yes
(16:36) FrankDuncan: That would get very ugly in lisp.
(16:36) SethTisue: shadowing the old binding. not updating it
(16:36) JoshUnterman: ok
(16:36) hellige: i'm going to tell you a secret, that won't make much sense now, but someday you will say "aha!"
(16:36) JoshUnterman: do it!
(16:36) Oliver_Gugenheim: are we supposed to understand this now?
(16:37) hellige: the whole interepreter is in "do-notation"
(16:37) kreig: so, the : operator
(16:37) hellige: which is the monadic part of haskell
(16:37) hellige: so a ghci session is just a big "do" block.
(16:37) hellige: which explains all the more "imperative" feeling parts of the interpreter.
(16:37) FrankDuncan: A HA!
(16:37) kreig: it's in a IO monad
(16:37) SethTisue: let's move on
(16:37) hellige: kreig: ?
(16:38) kreig: never mind me, I'm high on choco-leibniz cookies
(16:38) ChrisKeating: monads are how we parition off pure/impure code?
(16:38) hellige: ChrisKeating: among other things, yeah.
(16:38) kreig: I want to present, the : operator
(16:38) kreig: behold :, is cons
(16:38) hellige: indeed, is cons
(16:39) ChrisKeating: huzzah!
(16:39) JoshUnterman: :type :
(16:39) kreig: and it also, can decompose lists
(16:39) kreig: how awesome is that
(16:39) FrankDuncan: (:) 3 [1] makes me feel happy :)
(16:39) SethTisue: :type (:)
(16:39) kreig: hint: very awesome
(16:39) JoshUnterman: Prelude> :type (:) (:) :: a -> [a] -> [a]
(16:39) SethTisue: Josh: you have to put parens around the : to hand it to :type
(16:39) hellige: and it's only the beginning
(16:40) FrankDuncan: Wait, does haskell have pattern matching?
(16:40) hellige: FrankDuncan: of course
(16:40) ChrisKeating: how do you decompose a list with cons?
(16:40) FrankDuncan: hellige: Laugh, they hadn't mentioned it yet P
(16:40) ChrisKeating: :m pcre?
(16:40) hellige: :)
(16:40) SethTisue: pattern matching is covered in chapter 3
(16:40) hellige: ChrisKeating: different kind of pattern matching
(16:41) hellige: although of course they have that too
(16:41) kreig: ok, I am ready for ch2 when yall are
(16:41) haskelletor: so chap 3 is dispatch style stuff?
(16:41) sandover: not sure what you all had in mind to cover, but i'd be interested in the whole lastbutone question in Ch 2. particularly, how to do it efficiently?
(16:42) ChrisKeating: list decomposing?
(16:42) ChrisKeating: can anyone answer that?
(16:42) kreig: can I paste my solutions?
(16:42) SethTisue: chapter 3
(16:42) SethTisue: Josh asked what the base case is
(16:42) hellige: ChrisKeating: yeah, wait til chapter 3
(16:42) SethTisue: in my solution the base case is a two item list
(16:42) Oliver_Gugenheim: pasting solutions is good for me
(16:42) hellige: you can read it immediately following this meeting. :)
(16:42) Oliver_Gugenheim: for chap 2 exercise 2
(16:42) kreig: > lastButOne xs = if null (tail xs)
(16:42) kreig: > then head xs
(16:42) kreig: > else if null (tail (tail xs))
(16:42) kreig: > then head xs
(16:42) kreig: > else lastButOne (tail xs)
(16:42) FrankDuncan: sandover: Do you need it to be effecient?
(16:42) hellige: ok that's one solution
(16:43) hellige: let's see a different one
(16:43) Oliver_Gugenheim: I did
(16:43) SethTisue: http://hpaste.org/10957
(16:43) sandover: what is the working wiki URL?
(16:43) sandover: jinx!
(16:43) Oliver_Gugenheim: second_to_last a = last (take 1 (drop 1 (reverse a)))
(16:43) FrankDuncan: sandover: hrg.wikidot.org, I'll be better about getting it ready next weekend.
(16:43) gregfast: "Non-exhaustive patterns in function lb1" woot!
(16:43) hellige: Oliver_Gugenheim: NICE
(16:43) Oliver_Gugenheim: which throws an exception for 1 or 0 element lists
(16:44) hellige: Oliver_Gugenheim: i assume everybody errors out for a too-short list?
(16:44) hellige: what else would you do?
(16:44) SethTisue: mine is like Craig's but I just ignored the 1-item-list case
(16:44) Oliver_Gugenheim: and I'm not really sure about the parens
(16:44) hellige: i don't like craig's
(16:44) sandover: that iterates thru the whole list, which seems non-pleasing.
(16:44) hellige: i don't think it should return the last item of a 1-item list.
(16:44) hellige: sandover: it's a linked list. how can you not traverse it?
(16:45) SethTisue: other people can see my hpaste thing I assume?
(16:45) sandover: unless maybe the 'last' function also iterates?
(16:45) sandover: i don't know how it's implemented internally, m'boy
(16:45) hellige: SethTisue: i like yours more than craig's.
(16:45) sandover: that's not my biznatch
(16:45) hellige: sandover: yeah it iterates
(16:45) sandover: mourn
(16:45) gregfast: ooh, "last []" also fails, didn't know that
(16:45) hellige: whereof one cannot speak, one must throw an exception
(16:45) SethTisue: Josh do these answer your q?
(16:46) JoshUnterman: craig's also gives the incorrect answer on [1]
(16:46) JoshUnterman: it says 1
(16:46) hellige: yeah i don't like craig's
(16:46) hellige: (Num a) => a -> a -> a
(16:46) hellige: oops
(16:46) hellige: (Num a) => a -> a -> a
(16:46) hellige: dammit
(16:46) SethTisue: ?
(16:46) kreig: hehe
(16:46) ChrisKeating: kreig: they hate you man!
(16:47) hellige: i kinda cheated
(16:47) hellige: > lastButOne (x:_:[]) = x
(16:47) hellige: > lastButOne (_:xs) = lastButOne xs
(16:47) kreig: mine is correct
(16:47) hellige: they didn't introduce pattern matchin yet
(16:47) hellige: but anyway i like oliver's best
(16:47) hellige: except i would do it like this:
(16:47) kreig: if you planned on using it to buffer 8)
(16:47) JoshUnterman: one reason i had trouble is i tried to declare the type
(16:48) SethTisue: I put my lastButOne definition in a file
(16:48) SethTisue: but :type lastButOne doesn't work
(16:48) SethTisue: is there some way I can ask for the type?
(16:48) hellige: lb1 = last . take 1 . drop 1 . reverse
(16:48) kreig: I have another one:
(16:48) kreig: > lbo (x:y:[]) = x
(16:48) kreig: > lbo (x:y:ys) = lbo (y:ys)
(16:48) Oliver_Gugenheim: what do the dots mean?
(16:48) hellige: SethTisue: it doesn't?
(16:48) SethTisue: oh duh never mind sorry
(16:48) SethTisue: never mind
(16:48) SethTisue: http://icanhascheezburger.files.wordpress.com/2008/07/funny-pictures-cat-cannot-brain-today.jpg
(16:48) kreig: I don't know the _ thing that hellige used, but it makes sense now that we talked about thunks
(16:49) gregfast: (.) composes the functions
(16:49) Oliver_Gugenheim: so, why does my way need all the parens?
(16:49) JoshUnterman: from the comments:
(16:49) JoshUnterman: lastButOne xs = last (take ((length xs) - 1) xs)
(16:50) SethTisue: I think the parens are necessary, yeah
(16:50) sandover: hellige, why did you put 'last' in there?
(16:50) gregfast: because you're explicitly passing around the argument, i think
(16:50) hellige: yeah, basically
(16:50) gregfast: whereas matt used tricky curry-power
(16:50) hellige: but there is another way of avoiding parens
(16:50) haskelletor: yeah otherwise it'd be lbn
(16:50) SethTisue: what's lbn?
(16:50) hellige: it's weird at first
(16:50) hellige: but you'll get used to it
(16:50) FrankDuncan: hellige: If you do lastButOne (n:xs) = lastButOne xs instead of lastButOne (_:xs) = lastButOne xs, will it actually resolve n?
(16:50) haskelletor: i dunno lastbutn
(16:50) hellige: oliver's way, no parens:
(16:50) FrankDuncan: hellige: I thought it would be the same, as we odn't use n.
(16:51) hellige: lb1 xs = last $ take 1 $ drop 1 $ reverse xs
(16:51) hellige: people use ($) ALL THE TIME to prettify pipelines
(16:51) gregfast: frank it should bind the thing to n, but then never use it, which winds up being the same as using
(16:51) Oliver_Gugenheim: wait … what?
(16:51) sandover: the $ is held to be more beautiful than the . ?
(16:51) sandover: no accounting for taste
(16:52) ChrisKeating: are the dollar signs the same as .?
(16:52) Oliver_Gugenheim: . is the compose functions?
(16:52) Oliver_Gugenheim: $ is ?
(16:52) hellige: no
(16:52) FrankDuncan: Ok, so I understood that correctly, so you just use _ in order to to let other people know you won't be using it?
(16:52) hellige: they are different
(16:52) hellige: FrankDuncan: yeah, basically
(16:52) SethTisue: yeah, _ is like "don't care"
(16:52) hellige: ok, so
(16:52) gregfast: ($) means "put everything after this in a set of parens
(16:52) hellige: $ and .
(16:52) gregfast: "
(16:52) hellige: yeah
(16:52) hellige: there is NO DIFFERENCE
(16:52) Oliver_Gugenheim: that close where?
(16:52) hellige: between f x
(16:52) hellige: and f $ x
(16:52) hellige: except precedence
(16:52) JoshUnterman: this $ stuff is chapter 3?
(16:52) hellige: i'm sure it's not
(16:52) FrankDuncan: Hahahah
(16:53) kreig: oh, expressions
(16:53) hellige: FrankDuncan: i'm serious
(16:53) SethTisue: if anyone has strictly-chapter-2 stuff please cut in
(16:53) hellige: like
(16:53) hellige: literally
(16:53) hellige: this is in the prelude
(16:53) hellige: f $ x = f x
(16:53) FrankDuncan: hellige: Didn't think you weren't :)
(16:53) hellige: it's just used to make things prettier
(16:53) sandover: i did this, and it seems to work. Why? let lb_my = take 1 . drop 1 . reverse
(16:53) hellige: so a lot of times you can choose whether to use . or $ in a pipeline
(16:54) Oliver_Gugenheim: hmmm
(16:54) SethTisue: oh I was wondering about exercise 1
(16:54) hellige: and it depends on whether you have explicit argumetns or not. it's subtle
(16:54) SethTisue: "Haskell provides a standard function, last :: [a] -> a, that returns the last element of a list. From reading the type alone, what are the possible valid behaviours (omitting crashes and infinite loops) that this function could have? What are a few things that this function clearly cannot do?"
(16:54) Oliver_Gugenheim: perhaps I will understand how that can be prettier at some future point
(16:54) ChrisKeating: tuples…
(16:54) SethTisue: is this right?
(16:54) Oliver_Gugenheim: and how does it know where to close the parens?
(16:54) gregfast: omitting stuff is almost always prettier
(16:54) FrankDuncan: It could return a random element, the first element, the second one?
(16:54) ChrisKeating: so are tuples used to build complex data structures?
(16:54) SethTisue: the valid behaviors are to return the nth element of the list
(16:54) SethTisue: where n is any deterministic function of the length of the list?
(16:54) SethTisue: I think random is out
(16:54) JoshUnterman: lb_my returns [] when you give it [1]
(16:54) kreig: it could return a value of he list, with 5 added to it
(16:55) SethTisue: because if it's random it's not a true function
(16:55) FrankDuncan: SethTisue: I wasn't saying random as in rand()
(16:55) FrankDuncan: SethTisue: More in you randomly choose the 5th element and encode that.
(16:55) hellige: SethTisue: you are right
(16:55) Oliver_Gugenheim: kreig: could it? how do you know it is a list of things that can have 5 added to them?
(16:55) JoshUnterman: i'm outie.
(16:55) hellige: so the best lb1 seems to be
(16:55) JoshUnterman: see you all on the flipside.
(16:55) kreig: oh, excellent point
(16:55) hellige: lb1 = head . drop 1 . reverse
(16:55) SethTisue: Craig: Haskell lists are homogeneous
(16:56) kreig: yah, I forgot that the type constraint would percolate up
(16:56) hellige: JoshUnterman: bye!
(16:56) kreig: it has to be a blck box
(16:56) SethTisue: hey Glen you made it :-)
(16:56) nuckolls: well, I guess
(16:56) Oliver_Gugenheim: is there such a thing as "null"
(16:56) ChrisKeating: see you tomorrow josh
(16:56) SethTisue: Glen: someone will send a transcript to the mailing list
(16:56) Oliver_Gugenheim: as a return type?
(16:56) FrankDuncan: I'll post a transcript on the wiki :)
(16:56) hellige: Oliver_Gugenheim: depends what you mean.
(16:56) nuckolls: thanks
(16:57) kreig: how about mutate :: [(Num t)] -> t
(16:57) Oliver_Gugenheim: so, as an answer to exercise 1, of chap 2
(16:57) kreig: that would cover my "add five to an element" function
(16:57) Oliver_Gugenheim: could the function return 'nil'
(16:57) Oliver_Gugenheim: ?
(16:57) Oliver_Gugenheim: or "null"
(16:57) Oliver_Gugenheim: or "whatever the empty value is"
(16:57) FrankDuncan: Is there a null?
(16:57) Oliver_Gugenheim: that is my question
(16:57) gregfast: there's (), but it's not of any type except ()
(16:57) FrankDuncan: I don't think there's a null
(16:58) hellige: kreig: sure, but: Num t => [t] -> t
(16:58) FrankDuncan: Null is omni-typed, right?
(16:58) hellige: is the right way to write it.
(16:58) SethTisue: I'm pretty sure there's no null in Haskell?
(16:58) FrankDuncan: Can it return bottom?
(16:58) hellige: Oliver_Gugenheim: no
(16:58) gregfast: so no, you can't return () from a foo -> Num a function
(16:58) Oliver_Gugenheim: ok
(16:58) kreig: ah!, thank
(16:58) hellige: there is no null in haskell that is an element of every type
(16:58) haskelletor: what does the function null check for again?
(16:58) hellige: if you want null, you have to put it in
(16:58) hellige: like this: [t] -> Maybe t
(16:58) Oliver_Gugenheim: so, if that function is passed an empty list, if MUST throw an exception
(16:58) hellige: "Maybe t" basically means any t or else null (which we call Nothing)
(16:58) SethTisue: null the function checks if a list is empty
(16:59) haskelletor: right
(16:59) FrankDuncan: Oliver_Gugenheim: Yeah.
(16:59) hellige: Oliver_Gugenheim: yes, or else it must diverge
(16:59) Oliver_Gugenheim: diverge?
(16:59) hellige: FrankDuncan: your comment about bottom is dead-on
(16:59) hellige: Oliver_Gugenheim: never return, loop forever, whatever
(16:59) gregfast: so… how *does* last [] throw it's exception?
(16:59) Oliver_Gugenheim: aha
(16:59) hellige: or "return bottom" as frank says
(17:00) Oliver_Gugenheim: what is bottom?
(17:00) hellige: gregfast: i'm not sure. haskell's exception system is not too familiar to me
(17:00) hellige: i think there is a function error :: String -> a
(17:00) kreig: so
(17:00) hellige: that takes a message and raises an exception
(17:00) hellige: notice that it can take on ANY REQURIED TYPE
(17:00) kreig: is it better form to return Nothing from lastButOne [1]
(17:00) kreig: or raise an exception 8)
(17:00) gregfast: aha
(17:00) hellige: the type variable "a" is totally unconstrained.
(17:00) hellige: kreig: it would be better 90
(17:00) hellige: oops
(17:01) hellige: 90% of the time, to return Nothing
(17:01) hellige: but that would change the type
(17:01) gregfast: i was going to check the prelude source, but it killed firefox
(17:01) sandover: Abstractly, we denote the value of a non-terminating expression as _|_ (read "bottom"). Expressions that result in some kind of a run-time error, such as 1/0, also have this value. Such an error is not recoverable: programs will not continue past these errors. Errors encountered by the I/O system, such as an end-of-file error, are recoverable and are handled in a different manner.
(17:01) hellige: a lot of people have argued that the standard lib functions should have types like [a] -> Maybe a
(17:01) gregfast: http://haskell.org/hoogle <- awesome btw
(17:01) hellige: but i don't think there's total consensus. it's a little less convenient.
(17:01) SethTisue: if lastButOne can return Nothing the type must be Maybe a, is that right?
(17:01) hellige: SethTisue: yeah
(17:01) kreig: funny tho
(17:02) hellige: gregfast: yeah hoogle is amazing
(17:02) SethTisue: CLASS DISMISSED by the way, not that we can't keep chatting
(17:02) Oliver_Gugenheim: so …
(17:02) Oliver_Gugenheim: bottom means "this function does not return"
(17:03) haskelletor: sweet just finished the chapter
(17:03) hellige: Oliver_Gugenheim: yeah
(17:03) kreig: funny tho
(17:03) hellige: bottom is one of those math terms that leaked into common discourse in haskell
(17:03) kreig: hmmm
(17:03) hellige: i can explain where it comes from if you care
(17:03) Oliver_Gugenheim: sure
(17:03) kreig: that the type cannot include the length of the list
(17:03) Oliver_Gugenheim: seems very unfamiliar to me
(17:03) hellige: but generally, it just means "doesn't return, throws an exception, whatever"
(17:04) hellige: kreig: yeah. there are ways to hack that in haskell, but it's not natural.
(17:04) Oliver_Gugenheim: irrelevant alert: Sox are down 2-0 at the end of 3
(17:04) hellige: lots of research has gone into languages that can express that kind of thing in the type system.
(17:04) kreig: I mean check this:
(17:04) kreig: > lbo (x:y:[]) = x
(17:04) kreig: > lbo (x:y:ys) = lbo (y:ys)
(17:04) haskelletor: i remember bottom vaguely being representative of something in a pushdown stack machine or something
(17:05) hellige: haskelletor: not sure, i assume there is a connection though, if so.
(17:05) kreig: ok, so haskell can tell I need a two element list
(17:05) FrankDuncan: kreig: But that's a runtime constraint.
(17:05) hellige: kreig: yeah, it would be great
(17:05) FrankDuncan: kreig: It odesn' tknow if [a] satisfies that at compile time.
(17:05) hellige: FrankDuncan: don't be fooled, a lot of runtime constraints can be expressed in a sufficiently powerful type system
(17:05) kreig: I would expect the type to by (a:a:[a])
(17:05) FrankDuncan: hellige: Oh, yeah, I thought he was talking about haskell, not some theoretical haskell ;P
(17:06) kreig: it's a constraint known at compiletime
(17:06) FrankDuncan: hellige: I would want to hear real world examples of the length of a list being part of the type system as useful :)
(17:06) kreig: well, see tuples
(17:06) FrankDuncan: It seems like a "neat" idea, but is it actually necessary?
(17:06) hellige: kreig: i'm trying to find some of the crazy oleg code that actually does track and enforce those constraints
(17:06) SethTisue: I think most of the time if you wanted a two element list
(17:06) SethTisue: you would use a tuple instead
(17:06) hellige: but i can't find it quickly
(17:07) SethTisue: the whole point of lists is to be of variable length
(17:07) hellige: but YES you are absolutely right that we could in principle do that kind of stuff
(17:07) hellige: same with numbers
(17:07) hellige: like i should be able to statically eliminate a lot of divide-by-zero errors
(17:07) SethTisue: with tuples the # of items is part of the type
(17:07) kreig: yah, but I want a 2+ element list 8)
(17:07) hellige: but this is generally what we call "dependent typing" and it is a HUGE topic
(17:07) hellige: give it 5-10 more years.
(17:08) hellige: it's super interesting, though. really super interesting.
(17:08) kreig: gotta have dta-flow analysis nailed first
(17:08) nuckolls: why is restricting the number of elements "dependent" ?
(17:08) kreig: the better that is, the higher/sooner you can catch such things
(17:08) SethTisue: just off the top of my head, another way you could get something like a 2+ element list would be a 3-tuple (a,a,[a])
(17:08) hellige: because it's an instance of the general problem of types which depend on values
(17:09) hellige: because for instance
(17:09) hellige: you need to track that cons increases the length by 1
(17:09) hellige: and that appending a lists with lengths m and n
(17:09) hellige: results in a list with length m + n
(17:10) hellige: ok here we go
(17:10) hellige: if you want to freak yourself out
(17:10) hellige: http://okmij.org/ftp/Haskell/dependently-typed-append.lhs
(17:10) hellige: this is the tip of the iceberg
(17:10) nuckolls: so the dependent part depends on haskell specifics?
(17:10) hellige: yeah
(17:10) hellige: and in haskell it's REALLY ugly
(17:10) hellige: as that post demonstrates
(17:10) hellige: because the type system isn't really meant to do this
(17:11) hellige: so, for instance, to get numbers in the type system
(17:11) FrankDuncan: And how does one work with the infinite list?
(17:11) FrankDuncan: Because the tail of the infinite list is still infinite?
(17:11) hellige: you have to use peano naturals
(17:11) hellige: like Zero, Succ n
(17:11) hellige: FrankDuncan: one needs the fixpoint of Succ
(17:12) hellige: trust me, this is not natural in haskell
(17:12) hellige: it's amazing that you can do it at all
(17:12) hellige: if you're really interested in expressing this stuff in a type system, you need to look at languages that are meant for this
(17:12) kreig: well
(17:13) hellige: FrankDuncan: btw, that answer was a little glib… you really need to a coinductive types, which is complicated.
(17:13) kreig: with lisp you could have a runtime type check that did this 8)
(17:13) hellige: kreig: right, that's waht we do in haskell too. ;)
(17:13) hellige: choose your battles.
(17:13) hellige: haha
(17:13) kreig: but it owuld be party of the type system
(17:13) hellige: this is a funny thing that happens to people… it happened to me for sure
(17:13) kreig: deftype…
(17:13) hellige: people get a little taste of a powerful type system and they want more more more…
(17:13) SethTisue: bye everybody
(17:13) hellige: and when someone says "well it's not that powerful yet"
(17:14) hellige: they say, fuck it then, i'll just use ruby
(17:14) hellige: haha
(17:14) gregfast: ok, folks, see ya'll next time… thanks
(17:14) hellige: and i think that's kinda funny
(17:14) hellige: people want all or nothing.
(17:14) kreig: hmm
(17:14) FrankDuncan: :)
(17:14) hellige: but you know, i think the haskell system is a pretty good tradeoff for practical work
(17:14) hellige: unlike, say, java, which is just an annoying pain in the ass.
(17:14) kreig: I'm withholding my judgemne ton that for a few weeks 8)
(17:15) FrankDuncan: Now now, let's not become language snobs.
(17:15) hellige: :)
(17:15) kreig: java gives minimal WIN
(17:15) kreig: this is true
(17:15) FrankDuncan: I prefer a language that allows me to manipulate the reader at runtime :)
(17:15) Oliver_Gugenheim: I thought that was the point of this class? (to become language snobs)
(17:15) FrankDuncan: Well, I can remain a SmugLispWeenie if you like.
(17:15) nuckolls: that's what I'm hoping for :-)
(17:16) kreig: I ama lisp curmudgeon, not weenie!
(17:16) kreig: you kids with your shiny single paradigm languages
(17:16) Oliver_Gugenheim: next chapter has 12 exercises!
(17:16) hellige: Oliver_Gugenheim: yay!
(17:17) kreig: as if here is only one way to make sweet love to a computer!!!!
(17:17) hellige: ok yall
(17:17) hellige: i'm up out
(17:17) kreig: that's a apaddling
(17:17) hellige: everybody happy with our first meeting?
(17:17) Oliver_Gugenheim: thanks all!
(17:17) kreig: woot, back to real work now
(17:17) kreig: debuggin rubby
(17:17) sandover: i suggest a scaffold or structure next time
(17:17) hellige: sandover: yeah, we should do an agenda
(17:18) sandover: with maybe big marquees saying =========================== EX. 1 ====================
(17:18) hellige: ok see yall
(17:20) nuckolls: ok, will try to make the entire hour next time … see you all then
(17:20) sandover: thx all

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License