<    April 2017    >
Su Mo Tu We Th Fr Sa  
 2  3  4  5  6  7  8  
 9 10 11 12 13 14 15  
16 17 18 19 20 21 22  
23 24 25 26 27 28 29  
00:10 splanch joined
00:37 vaibhavsagar joined
00:42 andyhoang joined
00:44 des_ joined
00:49 eacameron joined
00:51 prophile joined
00:59 MotherFlojo joined
01:00 takle joined
01:02 conal joined
01:08 ljc joined
01:12 splanch joined
01:13 takle joined
01:15 conal joined
01:29 des_ joined
01:30 Haruna joined
01:31 Guest97307 joined
01:31 Guest97307 joined
01:32 splanch joined
01:32 approaching236 joined
01:33 \Mike joined
01:40 louispan joined
01:41 eacameron joined
01:45 takle joined
01:49 louispan_ joined
01:52 ebsen joined
01:59 takle joined
02:05 conal joined
02:07 Pupnik joined
02:11 andyhoang joined
02:15 takle joined
02:17 systemfault joined
02:19 exferenceBot joined
02:23 hexagoxel joined
02:26 ebsen joined
02:35 takle joined
02:40 uglyfigurine joined
02:44 des_ joined
02:45 MotherFlojo joined
03:04 takle joined
03:09 malaclyps joined
03:12 raduom joined
03:13 takle joined
03:31 MotherFlojo joined
03:33 Pupnik_ joined
03:41 MotherFlojo joined
03:46 splanch joined
03:50 mac10688 joined
04:05 louispan joined
04:30 uglyfigurine joined
04:41 Gurkenglas joined
04:41 takle joined
04:50 aarvar joined
04:55 takle joined
04:55 andreass joined
05:00 mitchty joined
05:03 splanch joined
05:13 louispan joined
05:19 AndiK joined
05:22 splanch joined
05:22 meandi_2 joined
05:26 andyhoang joined
05:26 splanch_ joined
05:28 splanch joined
05:29 takle joined
05:30 uglyfigurine joined
05:42 splanch joined
05:44 splanch_ joined
05:44 Pupnik joined
05:53 louispan joined
05:54 malaclyps joined
05:58 MotherFlojo joined
05:58 takle joined
06:09 alexelcu joined
06:11 <alexelcu> Hello. So in the interest of having pattern matching exhaustiveness checking, I've activated -Wall, but now I'm getting weird errors in the repl (using Emacs Intero and Stack)
06:13 <alexelcu> https://gist.github.com/alexandru/a1ae342ce7de6a6950046e75218f0f5d
06:15 <alexelcu> So from what I understood, in an "Identity 3" instance Haskell infers "Num a => Identity a", but then in order to print it, it has to default to a concrete type, which would be the Integer.
06:16 <alexelcu> But I don't understand why this is a warning.
06:20 sujeet joined
06:24 Lokathor joined
06:24 <alexelcu> Any way to deactivate it without removing -Wall?
06:26 <zaquest> -Wno-type-defaults?
06:28 sujeet joined
06:30 takle joined
06:32 <alexelcu> zaguest: thanks, that did it
06:34 davs joined
06:39 sujeet joined
06:43 takle joined
06:44 Sose joined
06:47 sujeet joined
06:48 approaching236 joined
06:50 MotherFlojo joined
06:53 davs joined
07:01 davs joined
07:10 davs joined
07:13 Zialus joined
07:16 <jle`> @tell alexelcu alternatively, Identity @Int 3
07:16 <lambdabot> Consider it noted.
07:18 sypwex joined
07:20 davs joined
07:23 Ferdirand joined
07:25 for{} joined
07:25 <for{}> hi
07:26 <for{}> when i use :t to find the signature/type i get sometimes `t`. why `t` and not `a`, for example?
07:26 alexelcu joined
07:32 takle joined
07:33 <MarcelineVQ> because it doens't matter what letter it is as long as it's consistent in a signature. for example a -> b -> a is the same as d -> g -> d
07:34 <for{}> i just wonder why t
07:34 <for{}> another question
07:35 <jle`> for{}: ghc tries its best to use the type variables that were used when defining the function
07:35 <for{}> `sumAll (x:xs) = x + sumAll xs; sumAll [] = 0` is as fast as `sumAll [] = 0;sumAll (x:xs) = x + sumAll xs`?
07:35 <jle`> @let someFunc :: q -> raddish -> horse; someFunc = undefined
07:35 <lambdabot> Defined.
07:35 <jle`> :t someFunc
07:35 <lambdabot> q -> raddish -> horse
07:36 <jle`> so if you get 't', it might be because whoever defined the function gave a type signature using t
07:36 <for{}> jle`, ok
07:36 <jle`> for{}: is that a question, or a statement?
07:36 <for{}> `sumAll (x:xs) = x + sumAll xs; sumAll [] = 0` is as fast as `sumAll [] = 0;sumAll (x:xs) = x + sumAll xs` ?
07:36 <for{}> a question
07:37 <MarcelineVQ> for{}: for that case they compile the same, I'm not sure how it works in general though
07:38 <for{}> yes, i know they output the same result, i just wonder which one is faster
07:39 <MarcelineVQ> I mean they compile to the same code
07:39 <for{}> doesnt order matter?
07:39 <MarcelineVQ> not for that one, I don't know about in general
07:40 <jle`> for{}: if you are really asking, it's not too hard to benchmark :)
07:40 <jle`> you can even use :set +s in ghci
07:40 <jle`> which times all commands
07:40 <jle`> or you can just compile it yourself
07:40 <jle`> and use `time` on unix
07:41 <jle`> i'd definitely trust those answers more than one i'd get on irc
07:41 <for{}> jle`, theres cache, there all sorts of tricks
07:41 <jle`> so do it more than once
07:41 <for{}> jle`, in your opinion, would the order matter?
07:41 <jle`> i don't know, but i know a really simple way to find out
07:42 <for{}> yes, you suggested
07:43 <jle`> this just reminds me of the time someone came in and asked what 'map succ []' returned
07:44 <jle`> and the response was, 'what happens when you try?'
07:44 <jle`> not saying that it's not a question worth asking, but, it's a question where the path to finding the answer yourself might be enlightening :)
07:45 nil_ joined
07:45 <jle`> if you do test it and it turns out that the answer is not what you'd expect, then it'd be interesting to ask the "why" question after.
07:45 <for{}> i cant build tests that output meaningful and accurate results
07:46 <for{}> linux kernel is so cunning :D
07:46 <MarcelineVQ> in my case I did :set -ddump-prep -dsuppress-all and tried your lines in ghci, they created the same ghc Core which is a small language that haskell code is turned into during compilation
07:47 <for{}> exactly the same?
07:47 <for{}> excuse me, im a total noob
07:48 <MarcelineVQ> As far as I can tell the same, some name changes happen you can't avoid, and there's been a desire for a tool that compares Core for awhile now. Core stuff isn't something one usually looks at before knowing the haskell end well so don't sweat it too much, that's how I determined your code wasn't different however
07:49 <for{}> oh, i thought you use some sort of diff, or a hash
07:50 <for{}> its just a matter of order, in this case. maybe compiler chooses every time one specific order
07:50 <MarcelineVQ> a robust diff tool for haskell AST's or Core is dstill esired by ghc devs
07:51 <for{}> should i be worried by the order of pattern matching as long as the code is correct?
07:52 <MarcelineVQ> That's a good question to ask, I would suggest that you don't worry about it, if you suspect it's a problem for something critical down the road that's a good time to delve into the machinery and see what's really going on
07:52 <jle`> don't worry about it unless it becomes a bottleneck later down the road
07:57 splanch_ joined
07:59 alexelcu joined
07:59 splanch__ joined
08:04 <MarcelineVQ> I'm still looking up the actual rules but a cursory investigation suggests that the order you write things in doesn't have a bearing because they'll be re-ordered later on, sometimes multiple times
08:04 <MarcelineVQ> *you write your declarations
08:05 alexelcu joined
08:06 <MarcelineVQ> the shape of your data declarations has more impact it seems, so something like data Maybe a = Nothing | Just a will scrutinize Nothing because it's defined first
08:07 colt44 joined
08:09 <MarcelineVQ> hmm, which also might not be the case, technically it's ordered by increasing constructor tag so now I need to find how things are tagged
08:09 alexelcu joined
08:10 takle joined
08:10 splanch joined
08:11 splanch_ joined
08:14 splanch__ joined
08:16 splanch joined
08:21 takle joined
08:23 MarcelineVQ joined
08:30 thc202 joined
08:37 tdfirth joined
08:52 davs joined
08:53 splanch joined
08:56 splanch_ joined
08:57 splanch__ joined
08:59 <rockfruit> Hi. Can anyone give me a clue why the following does not produce any output: http://lpaste.net/354169 I'm trying to solve https://www.hackerrank.com/challenges/eval-ex - so it's clues I need, but I'll settle for a direct answer :) Thanks
09:00 nacon joined
09:00 nacon joined
09:02 <MarcelineVQ> mmm, fact doesn't terminate I think
09:02 <rockfruit> the code does "terminate" - well hackerank does not complain of non-termination, just of "no output". Let me test locally.
09:03 <nil_> What MarcelineVQ said.
09:04 <nil_> fact needs an edge condition, a case where the result is something statically given.
09:04 <rockfruit> ok my machine is back off it's knees, you are right. thanks.
09:05 <rockfruit> I guess it would be hyper dumb of hackerrank.com to 'not terminate'.
09:06 <nil_> Yeah, it probably kills your submitted program after a few seconds.
09:12 <rockfruit> A quicky: I noticed that there are two operators ^ and ** which perform the same operation on different types. Why? In ghci I can say 1.8**8 and 8**1.8, also 8**8. So what is the purpose of having ^?
09:12 <mniip> :t (^)
09:12 <lambdabot> (Num a, Integral b) => a -> b -> a
09:12 <mniip> :t (**)
09:12 <lambdabot> Floating a => a -> a -> a
09:12 <mniip> :t (^^)
09:12 <lambdabot> (Integral b, Fractional a) => a -> b -> a
09:12 <mniip> different pecularities due to different types
09:12 <nil_> Exponentiation of Integrals can be optimized by exploiting the fact that the exponent is... an Integral.
09:14 <rockfruit> ok thanks. My first flash of thought when I saw this was that the types in haskell are a little 'too' static. but it's a math and speed thing, that makes a lot of sense to keep them all.
09:18 <rockfruit> What is the reason that haskell does not use a single operator, and switch the internals of the operation based on the types of the arguments? I thought it could just be because it would confuse the type inferencing?
09:19 <rockfruit> I'm not sniping... this kind of thing is all clues to me.
09:19 <MarcelineVQ> In general it's so when you mean to use a specific type and you don't the compiler can tell you
09:20 <mniip> rockfruit, you may want to use different ^ for the same type
09:21 <rockfruit> thanks.
09:21 <rockfruit> man it's a hard place, when you don't know enough fp to do anything useful, but you just caaaan't go back to python.
09:23 takle joined
09:25 t0by joined
09:26 louispan joined
09:27 <mniip> you definitely can and should
09:27 <mniip> haskell is not an ultimate tool
09:27 <mniip> nothing is
09:29 <rockfruit> I guess my problem is mainly the codebase - fp has a lot of lessons about avoiding smells.
09:33 initiumdoeslinux joined
09:44 takle joined
09:47 andrewhn joined
09:51 yellowj joined
09:54 <andrewhn> hello, wondering if someone can help me express something a little more ... functionally. I have the following definitions and helpers and I want to define addTrailInfo to track cumulative time and distance. http://lpaste.net/2958229987217375232
09:56 <andrewhn> essentially i want to map over the pairs while keeping track of the cumulative stats
09:56 <andrewhn> i'm getting a bit stuck on the functional side i think because there is no `mempty` if that makes sense
10:05 takle joined
10:13 MotherFlojo joined
10:16 Levex joined
10:18 netheranthem joined
10:18 eacameron joined
10:21 <jle`> andrewhn: is [GPSReading] -> [GPSReadingA] the function you want?
10:21 Prutheus joined
10:21 <jle`> and you want to map over pairs of [(GPSReading, GPSReading)] ?
10:21 <jle`> you can use mapAccumL, maybe, which is like "a map with state"
10:21 <jle`> :t mapAccumL
10:21 <lambdabot> Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)
10:22 <jle`> mapAccumL :: (s -> a -> (b, s)) -> s -> [a] -> (s, [b])
10:22 <jle`> instead of mapping an (a -> b), you map an (s -> a -> (b, s))
10:22 <jle`> so you get a state parameter you carry along
10:23 <andrewhn> that will work i think
10:23 <andrewhn> let me try
10:24 <raduom> Hi. Is there a setup emacs (25) with haskell tutorial that works at least as good as an atom installation?
10:26 wildlander joined
10:34 prophile joined
10:38 MotherFlojo joined
10:55 kritzcreek_ joined
11:05 <__rgn> why does (.) take a binary function as the first argument if :t (.) suggests arguments should be a unary functions? like (+) . (*2)
11:07 <mniip> there are no binary functions
11:07 <jle`> :t (.)
11:07 <lambdabot> (b -> c) -> (a -> b) -> a -> c
11:07 <mniip> a function of type 'x -> y -> z' is really a function of type 'x -> (y -> z)'
11:08 <__rgn> why does :t (.) seem to neatly satisfy case of composing two unary functions
11:08 <andrewhn> jle` thanks i ended up with this: http://lpaste.net/2958229987217375232 - haven't compiled yet but i think it should work. I ended up using foldr in the same way as you would use mapAccumL
11:09 <jle`> __rgn: because that's what it does
11:09 <jle`> (f . g) x = f (g x)
11:09 <jle`> andrewhn: yes you can implement mapAccumL in terms of folds
11:10 <jle`> it's just a convenient combinator so you don't have to implement it from scratch
11:12 <jle`> __rgn: (.) composes "unary functions", but 'unary' is redundant, becuase all functions in haskell are unary functions
11:14 <__rgn> the signature stops makign sense the moment i apply (+) to ti
11:14 <jle`> take it step by step
11:14 <jle`> what is the type of (+)?
11:15 <jle`> it's sort of a basic exercise in type unification
11:15 <jle`> for example, if (f :: Int -> Bool), and (g :: String -> Int)
11:16 <jle`> then if you did `f . g`, what are 'a', 'b', and 'c'?
11:16 <jle`> you just 'match up' the type variables with the known types you have
11:16 <jle`> (.) :: (b -> c) -> (a -> b) -> (a -> c)
11:16 <jle`> so if you applied it to an (Int -> Bool), then b is Int, and c is Bool
11:16 <jle`> (.) :: (Int -> Bool) -> (a -> Int) -> (a -> Bool)
11:17 <jle`> and if you apply it to an (Int -> Bool) and a (String -> Int), you know that 'a' is String
11:17 davs joined
11:17 <jle`> so the types unify if a ~ String, b ~ Int, and c ~ Bool
11:17 <jle`> (.) :: (Int -> Bool) -> (String -> Int) -> (String -> Bool)
11:17 <jle`> if that makes sense, then just apply the same step-by-step logic to (+) and (*2)
11:18 <__rgn> :t (+)
11:18 <MarcelineVQ> + might look tricky but mniip's insight is the one you need to unify a -> a -> a and b -> c
11:18 <lambdabot> Num a => a -> a -> a
11:18 <__rgn> how do you fit this there?
11:18 <jle`> so, (+) has to fit in for (b -> c), right?
11:18 <__rgn> yes, hence my problem
11:18 <jle`> so how do you fit `a -> (a -> a)` into `b -> c` ?
11:19 <jle`> it's sort of like matching variables in math
11:19 <__rgn> ok c becomes a -> a?
11:19 <jle`> if i have 'A x + B y = 5 x + 6 y'
11:19 <jle`> then i can infer that A is 5, and B is 6
11:19 <jle`> yes
11:19 <jle`> it's the exact same process we used before
11:19 <jle`> if i wanted to fit (Int -> Bool) into (b -> c)
11:19 <jle`> then b is Int, and c is Bool
11:20 <jle`> if you wanted to fit (String -> Double) into (b -> c)
11:20 <jle`> then b is String, and c is Double
11:20 <__rgn> well i wouldn't say exact because that one was obvious
11:20 <jle`> what is the difference?
11:21 <jle`> if you want to fit (Int -> (String -> Bool)) into (b -> c)
11:21 <jle`> then b is Int, and c is (String -> Bool)
11:21 <__rgn> structure changes, not just letters becoming types
11:21 <jle`> structure doesn't really change, though
11:21 <jle`> (Int -> Maybe Bool) and (b -> c)
11:22 <jle`> b is Int, and c is Maybe Bool
11:22 splanch joined
11:22 <jle`> the processes is the same, and it's pretty mechanical :)
11:22 <jle`> you might have been overthinking it
11:22 <jle`> the basic algorithm works the same way in every case
11:22 <jle`> (String -> Bool) is just a type, just like (Maybe Double), or Int
11:23 <jle`> to haskell's type system, they fill the same role
11:23 <jle`> there is no "different structure"
11:23 <jle`> they all are considered the same kind of thing :)
11:23 splanch_ joined
11:23 <jle`> if you think that structure is changing, you are definitely overthinking it :o
11:23 <MarcelineVQ> the strucure mentioned is likely the implicit ( ) of a -> (a -> a) which aren't normally shown so it can seem confusing
11:24 <jle`> __rgn: but, for something like (Int -> (String -> Bool)) and (b -> c), it really *is* just letters (variables) becoming types
11:25 <jle`> b is matched to the type 'Int', and c is matched to the type String -> Bool
11:25 <jle`> maybe you brought in some bias that considers 'Int' to be a type, but not 'String -> Bool' ?
11:25 splanch__ joined
11:29 splanch joined
11:29 <__rgn> i haven't had the insight that letter can expand into something with ->
11:31 <jle`> ah, yes, it can expand into anything :)
11:31 <jle`> well, any *type*, at least
11:31 <jle`> as long as it's a type, it can unify
11:31 <jle`> (a type of values)
11:32 <__rgn> maybe this insight will make other things make more sense
11:32 <jle`> but, my point was that the strategy is the same in both cases
11:32 <jle`> the same process that unites (Int -> Bool) and (b -> c) is the same process that units (Int -> Maybe String) -> (b -> c)
11:32 <jle`> and that would unite (Int -> (String -> Bool)) and (b -> c)
11:33 nil_ joined
11:33 <jle`> and the reason why is because Haskell treats all of those the same way
11:33 <jle`> it doesn't make the distinction "oh, this type has -> in it...let's treat it differently."
11:33 <jle`> it's the power of higher-order functions :)
11:33 <jle`> er, i mean, of first-class functions
11:34 <jle`> in other languages, functions are sort of ostracized and special-cased as their own thing
11:34 <jle`> but in haskell, functions are just normal values, and function types are just normal types.
11:35 nick_h joined
11:35 LordBugs joined
11:35 LordBugs left
11:35 LordBugs joined
11:40 <__rgn> thanks. appreciate the explanation
11:40 <jle`> no problem!
11:41 <__rgn> checking now if b -> c as b -> (a -> a) or so makes sense
11:42 <__rgn> or well a -> (a -> a)
11:47 <__rgn> would seem to
11:47 Prutheus joined
11:49 <__rgn> mind blown, sort of
11:49 eacameron joined
11:55 geekosaur joined
11:58 andyhoang joined
11:58 Pupnik_ joined
12:07 eacameron joined
12:08 splanch joined
12:10 splanch_ joined
12:11 splanch__ joined
12:12 splanch joined
12:14 splanc___ joined
12:15 <nil_> So we took Zeno to the vet today (don't worry, he's fine) and while we were waiting in the lobby I was thinking about how neat it is that Kleisli arrows always form a monoid under Kleisli composition... Except wait, they don't. You can't compose arbitrary Kleisli arrows like (f :: Monad m => a -> m b) and (g :: Monad m => c -> m d) unless b ~ c. So why do we formulate the Monad laws in terms of (>=>)? I'm confused.
12:19 eacameron joined
12:20 alexelcu joined
12:26 <MarcelineVQ> I don't know about that stuff but I would think you'd need to be able to compose to be under composition
12:27 dni- joined
12:27 <nil_> Kleisli arrows (newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }) compose just fine via (>=>).
12:32 <srhb> nil_: I'm confused. How is that different from having the arguments line up in regular function composition?
12:32 <MarcelineVQ> when the types align they compose just fine, not being able to fit f and g together there doesn't seem to have a relation to the first part though. If two things don't compose they're not under composition, I could be wrong about that terminology though
12:33 <MarcelineVQ> where do you see the Monad laws in terms of >=> btw, just so we're looking at the same things
12:34 <ski> s/always form a monoid/always form a category/
12:34 <nil_> srhb: hey, that's right. Now I'm more confused that ever.
12:34 <nil_> ski: hm, you're right about that.
12:35 <nil_> MarcelineVQ: https://wiki.haskell.org/Monad_laws , bottom of page.
12:36 <ski> (unrelatedly, thinking of the potential arguments there as `f :: Monad m => a -> m b' and `g :: Monad m => c -> m d' there is a misunderstanding)
12:36 <nil_> ski: elaborate please?
12:37 <ski> the potential arguments considered would be `f :: a -> m b' and `g :: c -> m d', where it is known that `Monad m'
12:37 <ski> this is not the same thing
12:37 <nil_> Oh, sure, I was playing fast and loose there.
12:38 <ski> having `x :: Cxt => T' is not the same as having `x :: T', with `Cxt' as a presupposition
12:39 <nil_> Totally right ofc.
12:39 <ski> (if you already understand this, then go ahead. i only mentioned it in case there was something to learn)
12:39 <nil_> Back to the central question: you're saying the Kleisli category associated with an arbitrary Monad m is /not/ required to be monoidal, yes?
12:39 <ski> yes
12:40 <ski> "category" is a generalization of "monoid"
12:40 <ski> and it's exactly the generalization you're looking for here
12:40 <nil_> ._. ...wow.
12:40 <nil_> That's totally it.
12:41 <ski> the laws "look the same", unless one explicitly writes out the "indices" of the composition and identity
12:41 <nil_> Okay, I don't get that one.
12:41 <ski> iow, instead of
12:41 <ski> id . f = f
12:41 <ski> f = f . id
12:41 <ski> (f . g) . h = f . (g . h)
12:41 <ski> which look like the laws for a monoid, we can write it as
12:42 <ski> id_B . f = f
12:42 <ski> f = f . id_A
12:43 <nil_> I get it. :)
12:43 <ski> (f ._{B,C,D} g) ._{A,B,D} h = f ._{A,C,D} (g ._{A,B,C} h)
12:43 <ski> assuming
12:43 <ski> id_A : A >---> A
12:43 Ferdirand joined
12:43 <ski> ._{A,B,C} : (B >---> C) * (A >---> B) >---> (A >---> C)
12:44 <ski> (one can express these as dinatural transformations)
12:44 <nil_> I was with you until the very last parenthesised line.
12:45 <ski> well, the types of the parameters there are
12:45 <nil_> What does it mean to be "dinatural"?
12:45 <ski> f : C >---> D
12:45 <ski> g : B >---> C
12:45 <ski> h : A >---> B
12:45 <ski> do you know what a natural transformation is ?
12:46 <nil_> I do.
12:47 <nil_> (Let's check though: a morphism in a category of functors?)
12:48 <ski> well, there you have `eta : F >---> G' (given `F,G : C >---> D' functors, `C',`D' categories) meaning that for every object `A' of `C', there is a morphism `eta_A : F A >---> G A' of `D', and for every two objects `A',`B' and every morphism `f : A >---> B' in `C', the equation `eta_B . F f = G f . eta_A' holds
12:50 stux|RC-only joined
12:50 <ski> yes, if you have two categories `C' and `D', the functor or exponential category `D^C' has as objects functors from `C' to `D', and as morphism natural transformations between those functors
12:50 <ski> also, there's a two-category `Cat' with `0'-morphisms (aka objects) being (small) categories, `1'-morphisms being functors, and `2'-morphisms being natural transformations
12:50 eacameron joined
12:51 Gurkenglas joined
12:52 <nil_> "for every A, B, f... the equation `eta_B . F f = G f . eta_A' holds" <=> "the square diagram between A, B, F(A) and F(B) commutes" , right?
12:52 <nil_> (<=> is "if and only if")
12:52 <ski> the square diagram has `F A',`F B',`G A',`G B' as corners. otherwise, yes
12:53 <nil_> Uh, right.
12:53 <ski> anyway, in `eta : F >---> G', `F' and `G' are both covariant functors. a contravariant functor from `C' to `D' can be construed as a (covariant) functor from `C^op' to `D' (or from `C' to `D^op', if you prefer), `C^op' being the opposite category of `C'
12:53 <ski> iow in `eta_A : ..A.. >--> ..A..', `A' occurs covariantly/positively in both the domain and the codomain, for an ordinary natural transformation !
12:54 <nil_> is a "2-morphism" in C a 1-morphism in the functor category built on top of C?
12:54 <nil_> I know what contravarian functors are btw.
12:55 <ski> in a two-category, given two objects / `0'-morphisms `A' and `B', the "hom-set" `Hom(A,B)' / `A >---> B' is itself a (`1'-)category
12:55 <nil_> Hmmmm...
12:56 <nil_> So what I said is basically a special case of the truth?
12:56 <ski> if the two-category has categories as objects, then this "hom-set", as a `1'-category, has functors as objects (and natural transformations as morphisms) .. it is the functor category `B^A'
12:56 <nil_> Okay, I think I'm following.
12:57 <ski> in general, the objects of a two-category needn't be categories, and so the (`1'-)morphisms needn't be functors (and the `2'-morphisms needn't be natural transformations)
12:57 <nil_> That's about what I thought, roughly.
12:58 <ski> (i'm still not sure which category `C' you were talking about, and what you meant by "the functor category built on top of C")
12:58 <nil_> By C I meant an arbitrary category. By the latter I meant the category of endofunctors in C.
12:59 <nil_> Sorry for loose terminology btw.
12:59 <ski> well, you asked about `2'-morphism, so it'd at least have to be an arbitrary two-category
12:59 <ski> (with emphasis on "two")
12:59 <nil_> I see
13:00 andyhoang joined
13:01 <ski> anyway, if you look at `compose_{A,B,C} : (B >---> C) * (A >---> B) >---> (A >---> C)', then you note that `B' occurs both co- and contra- variantly in the domain, and doesn't occur at all in the codomain
13:01 MotherFlojo joined
13:01 <nil_> Right.
13:01 <ski> and similarly for `identity_A : 1 >---> (A >---> A)', `A' occurs both co- and contra-variantly in the codomain, and not at all in the domain
13:02 <ski> `compose_{A,B,C}' is natural in `A' and `C', but not in `B'
13:02 <ski> dinatural transformations are supposed to be able to capture this kind of thing
13:05 <nil_> How come identity_A doesn't have type A >---> A?
13:05 <ski> we want morphisms between products of "hom-sets"
13:06 NoCreativity joined
13:06 <ski> in some cases, these won't be just sets. e.g. they could be abelian groups, `*' could be tensor product, and `1' not be the terminal object, but the group `|Z' of integers
13:09 <ski> (the general idea is similar to why, when we express "group in a monoidal category `<C,I,(*)>, we want a carrier object `G' in `C', and operations (morphisms in `C') `neutral : I >---> C',`combine : C * C >---> C',`inverse : C >---> C' satisfying some pointless laws involving the monoidal structure)
13:10 <nil_> I don't see how that relates to what you explained about dinaturality
13:12 Pupnik joined
13:12 <ski> (so if the monoidal structure has `lambda_B : I * B >===> B',`rho_A : A >===> A * I',`alpha_{A,B,C} : (A * B) * C >===> A * (B * C)' (satisfying some laws), then one of the group laws would be expressed as `combine . (id_C * neutral) . rho_C = id_C' ..)
13:12 <* nil_> is going to have to leave in about 15 minutes.
13:13 <ski> the point is that if we're talking about operations (such as composition) which operates on morphisms, then our domain and codomain should be objects (or products of objects) whose "inhabitants" are morphisms
13:14 <ski> and then the identity operation should also have a codomain whose inhabitants are morphisms, to "bring it to the same level"
13:14 <ski> (the domain of `identity' is then the empty product of "morphism objects" / "hom-sets")
13:14 <ski> anyway
13:14 <nil_> Oh, okay, that was somehow a lot clearer in English.
13:14 <nil_> Yeah, I'm with you now.
13:14 Ferdirand joined
13:15 <nil_> (The example was a bit too rich and detailed to illustrate such a simple point imo. :>)
13:16 <ski> the general idea is that we take two categories `C' and `D', and two functors `F,G : C^op * C >---> D'. then a dinatural transformation `kappa : F >-=-> G' consists of, for every object `A' in `C', a morphism `kappa_A : F (A,A) >---> G (A,A), such that for every objects `A',`B' and every morphism `f : A >---> B' in `C', `G(A,f) . kappa_A . F(f,A) = G(f,B) . kappa_B . F(B,f)' (hexagon law) is satisfied
13:17 <ski> the left side of the equation goes from `F(B,A)' to `F(A,A)' to `G(A,A)' to `G(A,B)'
13:17 <ski> the right side of the equation goes from `F(B,A)' to `F(B,B)' to `G(B,B)' to `G(A,B)'
13:18 <ski> iow, we're treating the co- and contra- variantly varying positions of `A' in `F (A,A)' and `G (A,A)' as two different object variables, but when we're using the dinatural transformation, they have to be instantiated to the same object
13:20 contiver joined
13:21 <ski> by starting from this concept, one can then express things like `identity : 1 >---> (forall A. A >---> A)' and `compose_{A,C} : (exists B. (B >---> C) * (A >---> B)) >---> (A >---> C)'
13:21 <ski> (`forall A. F (A,A)' being an "end" and `exists A. F (A,A)' being a "coend")
13:23 <ski> nil_ : makes any sense ?
13:26 <ski> (<https://etherpad.wikimedia.org/p/dinatural> contains some old scribbles on dinatural transformations. not sure whether it helps much. best viewed if you change the font in the settings to monospace)
13:27 <ski> (otherwise see <https://en.wikipedia.org/wiki/Dinatural_transformation>,<https://en.wikipedia.org/wiki/End_(category_theory)>, or the section in "Categories for the Working Mathematician" by Saunders MacLane)
13:30 <nil_> I'm def going
13:30 <nil_> to read all of that,
13:30 eacameron joined
13:30 <nil_> but right now I'm a bit tied up
13:30 <* ski> nods
13:30 <ski> have fun
14:01 andyhoang joined
14:16 dni- joined
14:18 Ferdirand joined
14:20 des_ joined
14:29 Gurkenglas joined
14:31 nick_h joined
14:32 conal joined
14:37 dni- joined
14:46 carlomagno joined
14:48 splanch joined
14:50 alexelcu joined
15:04 stef204 joined
15:06 andyhoang joined
15:06 deciduously joined
15:09 <lpaste> deciduously pasted “replaceThe” at http://lpaste.net/354173
15:09 Deide joined
15:09 <deciduously> hey all! i have a complete beginner question (this is literally week one for me)
15:09 <deciduously> im working through The Book - would anyone be able to tell me if it's better to use intercalate like shown in the paste or if I should just add spaces in my where clause and use init? does it make a difference?
15:09 <deciduously> thanks!
15:21 azahi joined
15:23 yellowj joined
15:30 eacameron joined
15:31 conal joined
15:50 splanch joined
15:55 <ski> @type unwords -- deciduously
15:55 <lambdabot> [String] -> String
15:55 <ski> @type fromMaybe "a"
15:56 <lambdabot> Maybe [Char] -> [Char]
15:56 <ski> @type elem
15:56 <lambdabot> (Eq a, Foldable t) => a -> t a -> Bool
15:57 <ski> > "the" `elem` ["The","the"]
15:57 <lambdabot> True
15:57 <ski> > map toLower "The" == "the"
15:57 <lambdabot> True
16:00 Levex joined
16:01 MotherFlojo joined
16:04 <deciduously> ah, not sure why I didnt reach for unMaybe
16:04 <deciduously> *fromMaybe
16:09 kritzcreek_ joined
16:10 <ski> (btw, it might be nicer to replace `The' with `A' ?)
16:12 <deciduously> true facts! that's more 'n' likely what you want :)
16:13 <deciduously> thank you
16:14 <deciduously> serious kudos to this book, never come across a more thorough set of exercises in one place
16:15 yigitozkavci joined
16:15 <yigitozkavci> Hi all, anyone available?
16:21 Nikotiini joined
16:22 mengu joined
16:24 Sose joined
16:24 conal joined
16:29 meandi joined
16:30 <qu1j0t3> yigitozkavci: probably best to just ask your question
16:48 mac10688 joined
16:48 davs joined
17:01 eacameron joined
17:02 NoCreativity joined
17:06 systemfault joined
17:07 approaching236 joined
17:08 malaclyps joined
17:08 eacameron joined
17:08 malaclyps joined
17:11 eacamero_ joined
17:15 argent0 joined
17:19 <alexelcu> In the @HaskellBook, page 303 (ereader, v0.12) the "newtype" is dropped in place and I find this confusing, because "data" would have worked and I don't understand the difference. Guess I'll find out later in the book, but wondering if there's any particular reason for why this sample uses it (I'm referring to the Numberish type class).
17:20 conal joined
17:24 arun_t joined
17:26 <arun_t> any one from india particularly from delhi/ncr region?
17:26 hoffmeyer joined
17:29 monochrom joined
17:29 prophile joined
17:31 stef204 joined
17:33 smichel17 joined
17:35 <hexagoxel> alexelcu: regarding semantics there probably is no difference, unless the topic is strictness of pattern matching.
17:35 <hexagoxel> alexelcu: for details, see https://github.com/quchen/articles/blob/master/fbut.md#data-newtype-type
17:41 prophile joined
17:41 <alexelcu> hexagoxel: ah, that makes it clearer, thanks
17:41 eklavya joined
17:41 exferenceBot joined
17:43 <alexelcu> I'm a Scala dev, I miss having a "newtype", it's pretty cool
17:44 malaclyps joined
17:44 <qu1j0t3> alexelcu: can;t you get something similar with value classes now?
17:45 <alexelcu> qu1j0t3: Value classes get boxed as soon as you store them. It's kind of a hack. Hopefully it'll get better with support from the JVM for those stack-allocated values.
17:46 <qu1j0t3> alexelcu: as soon as you store them?
17:46 <qu1j0t3> alexelcu: in a collection? not sure what you mean.
17:47 <qu1j0t3> alexelcu: don't they avoid boxing references, e.g. compared to a simple case class?
17:47 <hexagoxel> i bet "boxing" means different things in haskell, scala, and rust. :D
17:48 <qu1j0t3> hexaboxel
17:49 <qu1j0t3> arun_t: Just ask your question in the main channel.
17:49 <qu1j0t3> arun_t: DOn't be shy
17:49 <alexelcu> qu1j0t3: boxing as in initiating a class instance that gets stored on the heap, so it's in no way a zero cost abstraction, e.g. https://gist.github.com/alexandru/65557528af520c18030113c3f203beef
17:50 <alexelcu> Scala's value classes so far have proven useful for me only for "extension methods"
17:50 <qu1j0t3> alexelcu: hm, interesting. I'd consider this usage a corner case, however.
17:50 <qu1j0t3> alexelcu: if the member were a reference type to begin with (not Int), you'd see some, uh, value here, though?
17:50 <arun_t> qu1j0t3: I'm not shy I'm looking for people basically so I can start a Reading group/meetup !
17:50 <qu1j0t3> arun_t: good thing to mention in chan. :)
17:53 <alexelcu> qu1j0t3: well yes, even if you're wrapping a heap-allocated class instead of a primitive, it's still extra indirection; but primitives are my main use-case, because I basically need "units of measure" in my code (e.g. currently working with kilowatts, absolute or relative values, etc.)
17:53 pdgwien joined
17:53 eacameron joined
17:54 <qu1j0t3> alexelcu: I thought the point of value classes (primitives aside) is that you avoid one level of boxing. if not, what *is* the benefit?
17:54 <qu1j0t3> alexelcu: à la newtype, specifically)
17:57 <eklavya> alexelcu: if you only need primitives, aren't scala Value Classes the same as newtype?
17:57 <alexelcu> qu1j0t3: yes, that's the point of value classes, but because it lacks support from the runtime, so it doesn't really work :)
17:58 <qu1j0t3> alexelcu: I figure this is something the compiler can do statically. But like I said, i'm not an expert on value classes by any means.
17:59 x1n4u joined
17:59 <qu1j0t3> eklavya: alexelcu 's example above shows that this breaks down for primitives.
17:59 eacameron joined
17:59 <qu1j0t3> anyway i guess this is OT here
17:59 <* qu1j0t3> begs forgiveness
18:00 <* qu1j0t3> covers himself with leaves again
18:00 <MarcelineVQ> shunnnnn
18:01 <eklavya> qu1j0t3: yeah, only the most obvious and simple things will work without indirection in value class (it says that in the docs)
18:02 MotherFlojo joined
18:02 <qu1j0t3> WeakTea
18:03 deciduously left
18:03 mojjo joined
18:03 moei joined
18:04 <Cale> arun_t: There are lots more people in #haskell, so you probably want to try asking there as well, if you haven't already.
18:06 eacameron joined
18:06 jmiven joined
18:06 <arun_t> Cale: I'm a Beginner with haskell book also so this is the perfect place to ask , I will post there also
18:09 leothrix joined
18:09 Guest15908 joined
18:12 mreed0xfffffffff joined
18:15 <alexelcu> I'm using the Intero plugin with Emacs, it's great actually, but when I ask it to automatically insert a type for me, it adds "forall t." in front (e.g. "f :: forall t. Fractional t => t") … and that's apparently not valid syntax. Was wondering what the deal is there.
18:16 <geekosaur> ghci usually includes that, but you need an extension for it to be valid code
18:17 <Cale> It's a little odd that intero would turn on different language extensions than the code it was working with
18:18 davs joined
18:18 <geekosaur> I bet they didn't even think about it because half the other extensions turn on ImplicitForall
18:18 <geekosaur> er ExplicitForall derp
18:19 vitalij joined
18:19 <geekosaur> also I don;t recall a way to make ghci not include those forall-s in a :t and iirc that's what intero is using
18:22 eklavya left
18:22 <alexelcu> So what extension needs to be included? With a pragma?
18:22 <geekosaur> {-# LANGUAGE ExplicitForall #-}
18:23 <geekosaur> or just drop any leading 'forall something .' from any type it inserts
18:23 <lpaste> vitalij revised “Yesod persistent get”: “Yesod persistent get” at http://lpaste.net/354175
18:23 <alexelcu> geekosaur: thanks
18:27 <mreed0xfffffffff> hi, I'm having trouble with a problem in the Haskell Book and would appreciate some help
18:27 <mreed0xfffffffff> http://lpaste.net/354177
18:28 <glguy> mreed0xfffffffff: What led you to your expectation?
18:29 malaclyps joined
18:29 <mreed0xfffffffff> I figured that kessel's arguments are both not concrete types, since they lack any type annotations
18:30 <glguy> The 'b' type is defaulted to Integer, since it doesn't appear in the resulting type
18:30 <mreed0xfffffffff> so, it seemed that the result would also not be concrete; it would merely have a typeclass constraint
18:31 <glguy> But for the first argument, it's type didn't default. You appled kessel to an integer literal which has type Num a => a
18:31 <glguy> and kessel had a constraint on that argument of Ord a
18:31 <glguy> so you get both the Ord a from kessel, and the Num a constraint from using an integer literal
18:31 MotherFlojo joined
18:32 <glguy> Prelude> let kessel :: Ord a => a -> a; kessel = undefined; Prelude> :t kessel 1; kessel 1 :: (Num a, Ord a) => a
18:33 <glguy> 1 :: Num a => a
18:35 andyhoang joined
18:35 <mreed0xfffffffff> hmm, your example helps illustrate what is happening, but I don't understand why the b type (i.e., the Ord one) defaults to Integer
18:35 <mreed0xfffffffff> to be clear, I haven't gotten to ch. 6 yet, which goes more into typeclasses
18:35 <mreed0xfffffffff> apparently
18:37 merijn joined
18:38 <glguy> It defaults because Haskell has some special rules for defaulting types that would otherwise be ambiguous when they only use some of the built-in classes
18:38 <alexelcu> mreed0xfffffffff: Haskell is apparently very polymorphic, even the literals are, love it :)
18:38 <alexelcu> Q: Is there any way in ghci or in Emacs/Intero or some other extension to get the docs of a function or type, like what you can get from hackage? :info is only giving me the signature, which is useful, but I often find myself going to the web browser to search in hackage.
18:39 <glguy> mreed0xfffffffff: Section 4.3.4 https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-750004.3
18:41 takle joined
18:41 <alexelcu> mreed0xfffffffff: what's your background? what other languages have you used?
18:41 <mreed0xfffffffff> glguy: thank you, reading now
18:41 eacameron joined
18:42 <mreed0xfffffffff> alexelcu: C, Java, and POSIX sh; I'm finding Haskell's type system to be significantly more complex but also much more interesting
18:43 <mreed0xfffffffff> background: student
18:45 splanch joined
18:49 eacameron joined
18:54 eacameron joined
18:55 takle joined
19:01 eacameron joined
19:03 smichel17 joined
19:06 <mreed0xfffffffff> glguy: now that I've read this (https://stackoverflow.com/questions/42365769/why-num-a-ord-a-a), I get what you said earlier about the result getting the constraint from both the integer literal (Num a => a) and kessel (Ord a => a)
19:06 <mreed0xfffffffff> thanks for the help :)
19:10 hellofunk joined
19:18 darkvaadoor joined
19:20 takle joined
19:26 delexi joined
19:27 takle joined
19:28 <alexelcu> mreed0xfffffffff: it helps if you view type-classes as Java-like interfaces, but with big differences. Java OOP interfaces describe instance methods, whereas type-classes are for the types (classes in Java) themselves - in Java think of being able to have polymorphic static methods.
19:29 <alexelcu> It simplifies some things. In Java you can't describe a Num or a Monoid interface easily, because while you can describe "plus", you also need a "zero".
19:29 <alexelcu> There are also no wildcard-powered covariance / contravariance shenanigans.
19:30 <ski> (referring to ?)
19:30 <alexelcu> Previous discussion, sorry if this is noisy
19:30 eacameron joined
19:31 <ski> no, i mean, what does "wildcard-powered covariance / contravariance" refer to ?
19:31 <ski> (also in which language ? Haskell or Java ?)
19:31 <qu1j0t3> that would be java.
19:36 andyhoang joined
19:36 <alexelcu> So speaking of working with Ord, it's pretty neat compared with: <T extends Comparable<? super T>> void sort(List<T> list)
19:38 alexelcu joined
19:39 zero_byte joined
19:39 Levex joined
19:41 takle joined
19:42 <raduom> I think Ord would be more like Comparable.
19:43 <raduom> In Java you can have what is called the Adapter pattern which functions like type classes, with the caveat that you do not have any compile time safety.
19:46 davs joined
19:50 takle joined
19:53 eacameron joined
19:54 malaclyps joined
19:56 \Mike joined
20:02 louispan joined
20:10 <Durbley> [1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
20:10 <Durbley> can someone show me where the parentheses are in this
20:10 <Durbley> so I can understand the order
20:11 <ski> [1,2] >>= (\n -> (['a','b'] >>= (\ch -> return (n,ch))))
20:15 Levex joined
20:19 eacameron joined
20:27 aarvar joined
20:30 yellowj joined
20:36 eacameron joined
20:42 eacameron joined
20:45 dni- joined
20:46 des_ joined
20:46 Durz0 joined
20:46 nil_ joined
20:48 MotherFlojo joined
20:49 splanch joined
20:52 splanch_ joined
20:55 eacameron joined
21:04 eacameron joined
21:07 alexelcu joined
21:10 eacameron joined
21:12 louispan joined
21:14 eacameron joined
21:18 eacameron joined
21:18 splanch joined
21:19 MotherFlojo joined
21:20 Big_G joined
21:23 eacameron joined
21:28 <Durbley> ski, thanks. idk if this is particularly useful but can you tell me if this evaluation is correct
21:28 <Durbley> https://pastebin.com/icUHg358
21:28 albertus1 joined
21:31 <ski> Durbley : apart from a spurious `(' on line 3, it's correct, yeah
21:31 <Durbley> ski, is it useful to look at it this way
21:31 <ski> @src [] (>>=)
21:31 <lambdabot> xs >>= f = concatMap f xs
21:32 <ski> concatMap f xs = concat (map f xs)
21:32 <Durbley> [(n, c) | n <- (1,2), c <- ('a', 'b')]
21:32 <Durbley> when i look at it this way it makes perfect sense
21:32 <ski> @undo [(n,ch) | n <- [1,2],c <- ('a','b')]
21:32 <lambdabot> concatMap (\ n -> concatMap (\ c -> [(n, ch)]) ('a', 'b')) [1, 2]
21:32 <Durbley> ye
21:33 <Durbley> is that what you instantly think when you see the list monad?
21:33 <ski> (er, with square brackets, not a pair)
21:33 <Durbley> yeah
21:33 <Durbley> u rite
21:33 <ski> @undo do n <- [1,2]; c <- ['a','b']; return (n,ch)
21:33 <lambdabot> [1, 2] >>= \ n -> ['a', 'b'] >>= \ c -> return (n, ch)
21:33 <ski> list comprehension is basically list monad, yes
21:34 <ski> and it's all about "nesting loops", if you will
21:34 <Durbley> when I actually broke done that evaluation I did it pretty much totally mechanically
21:34 <* ski> nods
21:34 <Durbley> it's unintuitive to me to work from the definition
21:34 <Durbley> but I understand the list comprehension intuition (i think)
21:35 <Durbley> what is >> in the context of the list monad
21:36 <Durbley> is there a comprehension analogy?
21:36 <ski> > [ch | _ <- [1,2],ch <- ['a','b']]
21:36 <lambdabot> "abab"
21:36 <ski> a silly way of repeating as many times as there's elements of the list, not looking at the elements
21:37 <ski> with a tree monad, it'd possibly be more useful
21:37 <Durbley> what would that be using >>= or do notation
21:37 andyhoang joined
21:38 <Durbley> do _ <- [1,2]; ch <- ['a','b']; return ch
21:40 <ski> yes, or just `do [1,2]; ch <- ['a','b']; return ch'
21:40 <ski> @undo do [1,2]; ch <- ['a','b']; return ch
21:40 <lambdabot> [1, 2] >> ['a', 'b'] >>= \ ch -> return ch
21:41 <ski> @undo do _ <- [1,2]; ch <- ['a','b']; return ch
21:41 <lambdabot> [1, 2] >>= \ _ -> ['a', 'b'] >>= \ ch -> return ch
21:41 smichel17 joined
21:44 <Durbley> whats the definition of >> for lists
21:44 <Durbley> @src [] (>>)
21:44 <lambdabot> xs >> ys = concatMap (const ys) xs
21:44 <Durbley> g0t it
21:44 <Durbley> @src const
21:44 <lambdabot> const x _ = x
21:46 <monochrom> Or you can understand it from the point of view of xs >> ys = xs >>= \_ -> ys
21:46 <ski> @src (>>)
21:46 <lambdabot> m >> k = m >>= \_ -> k
21:50 xificurC joined
21:51 <xificurC> how can one check for point-free definition of something here?
21:52 <monochrom> Like this?
21:52 splanch joined
21:52 <monochrom> @pl f x = x x
21:52 <lambdabot> f = join id
21:52 <monochrom> Bad example but :)
21:52 <xificurC> monochrom: thanks
21:52 <xificurC> let's see
21:52 <xificurC> @pl validate n = rem (sumDigits (doubleEveryOther (toDigits n))) 10 == 0
21:52 <lambdabot> validate = (0 ==) . flip rem 10 . sumDigits . doubleEveryOther . toDigits
21:53 <xificurC> ok not worth it :)
21:53 <ski> amazingly, that's pretty readable
21:53 hiratara joined
21:53 <* ski> would use a section with `rem', though
21:53 <xificurC> @pl validate n = sumDigits (doubleEveryOther (toDigits n)) `rem` 10 == 0
21:53 <lambdabot> validate = (0 ==) . (`rem` 10) . sumDigits . doubleEveryOther . toDigits
21:53 <ski> aye
21:54 <monochrom> Yeah, this actually is a nice pipeline.
21:54 <nil_> monochrom, s/bad example/awesome example/ imo.
21:54 <xificurC> my first reaction would be to write
21:54 <monochrom> It is bad because it is a type error :)
21:54 <ski> people tend to not like `Monad (rho ->)' so much in serious code
21:54 <ski> (heh, that too)
21:55 <xificurC> validate n = foo n `rem` 10 == 0 where foo = sumDigits . doubleEveryOther . toDigits
21:55 <xificurC> but yeah, the non-flip version looks pretty neat
21:56 <monochrom> Customers who like the (->)r monad may also like: http://lpaste.net/91519
21:56 dkeathley joined
21:59 <xificurC> I had a bit of a puzzle earlier writing something like (mappend (+1) [1,2,3]) and wondering why don't the types match :)
21:59 splanch joined
22:00 <xificurC> actually that's a bad example, should have been (mappend (:]
22:00 <xificurC> mappend (:[]) [1,2,3]
22:01 <monochrom> I mistype Handle as Handel all the time when coding in Haskell.
22:01 <monochrom> The irony is I also mistype Handel as Handle when entering classical music tags.
22:02 <* ski> typoes "typo" as "type"
22:02 vicfred joined
22:02 <nil_> Where do you find that you need to enter classical music tags?
22:03 <Durbley> guys im learning about the functor, applicative, and monad for functions for the first time
22:03 <Durbley> and it confuses the shit out of me
22:03 <Durbley> is this normal
22:03 <nil_> Durbley, it is. :)
22:03 <Cale> Durbley: anything I could help clear up?
22:04 <Cale> Durbley: If you focus on the types that the operations have to have, you'll find that their implementation is basically forced
22:04 <monochrom> When I don't like the tags from the Internet.
22:05 <nil_> Durbley: Relax, the euphoric feeling of enlightenment at the other end of the tunnel will also be normal.
22:05 <Cale> Durbley: For the Monad instsance, it might help to look at some examples...
22:06 <monochrom> Start with functor. It is pretty tame.
22:06 <Durbley> if you say "the functor is just composition" then I feel okay about it since I understand composition
22:06 <Durbley> but I don't really understand how everything is being represented
22:06 <Durbley> ((*3) <$> (+1)) 1
22:06 dkeathley joined
22:06 <monochrom> But functor is not just composition.
22:06 <Durbley> for example this isn't hard to trace if I understand it as composition
22:06 <Durbley> but I don't know step-by-step how this is being evaluated
22:06 <Cale> monochrom: Well, we're only talking about the instance for functions
22:06 <Cale> fmap really is just composition there :)
22:06 <monochrom> Oh, then yes.
22:07 <Cale> Durbley: Well, (<$>) is just infix fmap
22:07 <Cale> In general, we have
22:07 <Cale> fmap :: (Functor f) => (a -> b) -> f a -> f b
22:07 <Cale> If we plug in f t = e -> t
22:07 <Cale> then this becomes
22:07 <monochrom> But that is the same kind of lazy thinking as "perhaps an advanced alien civilization seeded life on Earth".
22:08 <Cale> fmap :: (a -> b) -> (e -> a) -> (e -> b)
22:08 <Cale> which is exactly the type of function composition
22:08 <Durbley> okay so what exactly is (->)
22:08 <Durbley> I've read that it's a function
22:08 <Durbley> but it's confusing because it's used in the type declaration of functions
22:08 <Cale> (->) is the type constructor for functions
22:09 <Cale> Remember that basically anything infix, you can write it prefix by putting it in parens
22:09 <Durbley> yes
22:09 <Durbley> got it
22:09 <Durbley> but in type declarations is it the same ->
22:09 <Cale> So, when you write something like A -> B for the type of functions taking an argument of type A and producing a result of type B
22:09 <Cale> You could also write that as (->) A B
22:09 <Cale> Or even, to be more explicit about parens, ((->) A) B
22:10 <Durbley> are type constructors functions
22:10 <Cale> Not always, but this one is a (type level) function.
22:10 <Cale> :k (->)
22:10 <lambdabot> * -> * -> *
22:11 <Cale> * is the kind of ordinary types which may have values
22:11 <Durbley> concrete types
22:11 <Cale> * -> * is then the kind of type level functions which take a type of kind * and produce another type of kind *
22:12 <Cale> :k IO
22:12 <lambdabot> * -> *
22:12 <Cale> :k Maybe
22:12 <lambdabot> * -> *
22:12 <Cale> and * -> * -> * would be the kind of type level functions which take a type of kind *, and produce a type level function of kind * -> *
22:13 <Cale> which is the same thing as something which takes two types of kind * and produces a type of kind *
22:13 <Durbley> you said type constructors aren't always functions
22:14 <Durbley> but aren't nullary type constructors still functions
22:14 <Cale> Right, for example, Integer is a type constructor, but it's not a type level function
22:14 <Cale> I would only call something a function if the top-level thing in its type (or kind) was an ->
22:15 <Durbley> top-level?
22:15 <Cale> If you think of it in terms of the parse tree :)
22:15 <Cale> Like, the outermost thing
22:16 <Durbley> i c
22:17 <Durbley> ((*3) <$> (+1)) 1
22:17 <Cale> I'd hesitate to call something of type [a -> b] a "function" for example, it's primarily a list
22:17 <Durbley> what does haskell immediately do to evaluate this
22:17 <Cale> Well, it evaluates the (<$>)
22:17 <Cale> Well, note that it will first typecheck the expression
22:18 <Durbley> @src (->) (<$>)
22:18 <lambdabot> Source not found. Sorry about this, I know it's a bit silly.
22:18 <Durbley> =\
22:18 <Durbley> @src -> (<$>)
22:18 <lambdabot> Source not found. I can't hear you -- I'm using the scrambler.
22:18 <Cale> @src (->) fmap
22:18 <lambdabot> fmap = (.)
22:18 <Durbley> I see
22:18 <Durbley> I guess it's confusing to me how functions are types
22:19 <Cale> So having typechecked the expression, it will discover what type (<$>) must have, and which instance of Functor must be in use
22:19 <lpaste> mac10688 pasted “Problem?” at http://lpaste.net/354182
22:19 <Cale> It will supply the implementation from that instance
22:19 <Cale> @src (.)
22:19 <lambdabot> (f . g) x = f (g x)
22:19 <Cale> and it will do that
22:19 <Cale> So we get (*3) ((+1) 1)
22:19 <glguy> mac10688: Int isn't a typeclass
22:20 <glguy> mac10688: The type would just be: Maybe Int -> Int
22:20 <monochrom> Right, you want simply Int -> Maybe Int.
22:20 <monochrom> Err, Maybe Int -> Int.
22:20 <mac10688> glguy, thanks! It makes perfect sense now.
22:20 <Cale> and then we'll get ((+1) 1) * 3
22:20 <Durbley> i c Cale
22:20 <Durbley> can you explain why it makes sense that functions are types
22:21 <Cale> I wouldn't say "functions are types"
22:21 <Cale> There is a type for functions
22:21 <Cale> and there are type level functions
22:21 <Cale> But if you said "function" without context, I'd probably think you meant a value-level function
22:21 <Cale> e.g. reverse is not a type
22:22 <Cale> But Either is a type
22:22 <Cale> :k Either
22:22 <lambdabot> * -> * -> *
22:22 dejanr joined
22:22 splanch joined
22:22 <Cale> It's a type level function which can take some arguments in order to produce a type which has values
22:23 splanch_ joined
22:25 louispan joined
22:25 splanch__ joined
22:26 <Cale> Durbley: similarly (->) is a type level function which takes two ordinary type arguments to produce an ordinary type
22:26 <Cale> Right?
22:26 <Cale> :k (->)
22:26 <lambdabot> * -> * -> *
22:26 <Cale> :k (->) Integer
22:26 <lambdabot> * -> *
22:26 <Cale> :k (->) Integer String
22:26 <lambdabot> *
22:26 splanch joined
22:26 <Cale> :t show :: (->) Integer String
22:26 alexelcu joined
22:26 <lambdabot> Integer -> String
22:27 <Cale> All instances of Functor in Haskell are types of kind * -> *
22:27 <Cale> :k Functor
22:27 <lambdabot> (* -> *) -> Constraint
22:28 <Cale> Durbley: still there?
22:28 splanch_ joined
22:28 <lpaste> mac10688 pasted “position not in scope?” at http://lpaste.net/7021715987825164288
22:28 <xificurC> there was a post I liked a few years ago that showed FAM with pictures of boxes
22:29 <xificurC> can't remember what was in the box that was being taken out anymore
22:29 <monochrom> I think those pictures are wrong.
22:30 <xificurC> did you guys get an enlightenment moment when it just all clicked, or was this natural for you, or was it a lot of hard work
22:30 <monochrom> mac10688: Your "position <-" is too late.
22:30 <geekosaur> mac10688, ^ you need to reverse those
22:30 <xificurC> monochrom: too bad, I still think about it that way
22:30 splanch__ joined
22:31 hiratara joined
22:31 <nil_> xificurC: I think it's a gradual process. You understand it a bit better each time you come back to it or look at the classes from a different angle.
22:31 <mac10688> oh geez lol
22:31 <monochrom> It was all three.
22:31 <Cale> xificurC: The thing which made me understand Monad was looking at good examples of monads.
22:32 <Cale> The tipping point for me was Parsec
22:32 <monochrom> And what Cale said. Why a lot of work, but also quite natural.
22:32 <Cale> (or generally parser combinators, there's nothing too special about Parsec vs others)
22:32 <xificurC> Cale: I don't just mean monads, that's like the beginning
22:32 dejanr joined
22:32 <monochrom> And by the time of a parser monad, why there was a click too.
22:33 <xificurC> I'm back to haskell as I'd like to write an interpreter
22:33 andrewhn joined
22:33 <Cale> xificurC: Well, if you understand Monad, the rest is reasonably simple.
22:33 <monochrom> What happened was that I learned the standard examples like [], Maybe, IO, s->(a,s), r->a. They were quite OK.
22:34 <monochrom> And then a parser monad really opened my eyes what else is possible.
22:34 <xificurC> Cale: I was here for ~6 months some years ago, I think I got monads but got lost at monad transformers
22:34 <Durbley> Cale, I'm here and reading
22:34 dni- joined
22:34 <Durbley> got some food
22:34 <xificurC> then I hopped, like I always do
22:34 <Cale> Durbley: cool
22:34 <monochrom> Or maybe it was just "you need 10 examples for critical mass" and it would not quite matter which 10.
22:34 eacameron joined
22:34 <Durbley> Cale, what is the definition of the (->) type
22:35 <Cale> Durbley: Well, it's built-in.
22:35 <ski> no definition, it's abstract, just like `Int' and `Double'
22:35 <Durbley> hm
22:35 <monochrom> I do think you need to look for critical mass instead of that supertitious fictional fantasy called "enlightenment".
22:35 <ski> (and `IO')
22:35 <monochrom> Programming is a science not a Zenist religion.
22:35 <Cale> Durbley: But it takes the type for the domain of the function, and the type for its codomain, and produces the type of such functions
22:35 <nil_> monochrom: enlightenment is hardly a fantasy imho.
22:36 <Durbley> lol how fast haskell talk turns to religion
22:36 Pupnik joined
22:36 <monochrom> As fast as programmers behaving unscientifically?
22:37 <Durbley> what is behaving unscientifically
22:37 <monochrom> You should research on that.
22:37 <Durbley> lol
22:38 <xificurC> monochrom: I'm not sure what you mean by "critical mass", but in my case it's usually that after some amount of real-life usage it clicks why something's useful
22:39 <xificurC> pardon for that clunky sentence
22:39 andyhoang joined
22:39 <monochrom> That is accumulating a critical mass of experience.
22:40 conal joined
22:41 <monochrom> In the meantime, the IO system is monadic, so it is a necessity anyway.
22:41 dejanr joined
22:43 <monochrom> But if you can also translate list comprehension into do-notation, and then to using >>=, and you see how it is a mechanical translation, that is a valuable connection.
22:44 <xificurC> there's always unsafePerformIO :)
22:44 <monochrom> And next time you see "case m of Nothing -> Nothing; Just x -> sin (x+4)", you think "oh, but it's fmap (\x -> x+4) m", that's also a valuable connection.
22:45 <* ski> inserts a `Just'
22:45 <monochrom> err, s/sin (x+4)/Just (sin (x+4))/, yeah
22:45 <xificurC> monochrom: haven't you dropped a Just?
22:45 <ski> you should also recognize `return . f =<< m' as `fmap f m'
22:45 <monochrom> Or if you see the mistake and can suggest an erratum, that's also shows understanding. :)
22:46 dejanr joined
22:46 <xificurC> I'm not a lost cause
22:46 <monochrom> But overall look how I portrait understanding as "you can do things, you can predict things". Not as "you can write an essay".
22:48 <monochrom> Also I forgot a "sin" in the fmap version.
22:48 <monochrom> should have stuck with x+4
22:48 <xificurC> it's "you do things, you understand things" or "you don't understand things, you write"
22:48 zero_byte joined
22:48 <xificurC> ^ joke
22:48 <xificurC> good night guys
22:48 malaclyps joined
22:50 <geekosaur> sounds like monad tutorials >.>
22:51 <monochrom> heh
22:52 <monochrom> Clearly, can't say dons didn't understand monad, but when he wrote the spacesuit story, that certainly hurt.
22:53 <monochrom> The human mind has this flawed tendency that when it can express in words, it feels good about itself.
22:53 <monochrom> And nonetheless still cannot predict what a simple piece of code does.
22:54 <monochrom> Or not even whether another short piece of code is a type error or not.
22:59 patbecich joined
22:59 earldouglas joined
23:05 eacameron joined
23:20 patbecich joined
23:24 dkeathley joined
23:28 ljc joined
23:29 OscarZ joined
23:34 mjs2600 joined
23:34 mjs2600 left
23:40 andyhoang joined
23:41 splanch joined
23:41 conal joined
23:43 splanch_ joined
23:50 splanch_ joined
23:52 nick_h joined
23:54 louispan joined
23:57 <lpaste> mac10688 pasted “How to debug?” at http://lpaste.net/354184
23:57 <mac10688> so in other languages I would set breakpoints and examine the variables, but in Vim I don't have that option
23:57 <mac10688> I tried using traceShow and stuff like that, but the values never printed to the terminal
23:58 <mac10688> anyone have a good idea of how to debug this code? I just want it to print out variables as it evaluates them
23:58 <mac10688> putStrLn doesn't really work in the inner functions
23:58 <mac10688> or non-IO functions