<    March 2017    >
Su Mo Tu We Th Fr Sa  
          1  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 30 31
00:00 bydo joined
00:00 <boxscape> reptar_: well, not in haskell, not with any reasonable type anyway. In untyped lambda calculus, you can, because it doesn't have types
00:03 <reptar_> that's not very intuitive
00:04 <boxscape> well, you just treat it like anything else. If you have (λx.xy)(λx.xy), it's not any harder to do beta reduction than on any other term
00:07 <reptar_> guess i'll just have to give it time
00:07 <ExpHP> can lambdabot tell you what module a std library function is in?
00:07 <ExpHP> @whereis ap
00:07 <lambdabot> Maybe you meant: where+ where
00:07 <boxscape> reptar_: don't worry too much about the particulars of lambda calculus if you want to learn haskell - especially if they're different from haskell
00:09 <reptar_> good point
00:09 <reptar_> it's so easy to get distracted XD
00:09 <boxscape> ExpHP: you can look through its commands with @listmodules, but it doesn't look to me like there is anything
00:10 <boxscape> well, it's modules, each of which may have 0-n commands
00:10 <reptar_> @karma+ boxscape
00:10 <lambdabot> boxscape's karma raised to 1.
00:10 <ExpHP> @hoogle ap
00:10 <lambdabot> Control.Monad ap :: (Monad m) => m (a -> b) -> m a -> m b
00:10 <lambdabot> Data.Graph.Inductive.Query.ArtPoint ap :: (Graph gr) => gr a b -> [Node]
00:10 <lambdabot> Monad ap :: Monad m => m (a -> b) -> m a -> m b
00:10 <boxscape> yay
00:12 <geekosaur> @index ap
00:12 <lambdabot> Control.Monad
00:12 <ExpHP> le gasp
00:12 <geekosaur> but this only works for a handful of things
00:12 <ExpHP> @index either
00:12 <lambdabot> Data.Either, Prelude
00:13 <ExpHP> @index Generic
00:13 <boxscape> @index (+)
00:13 <lambdabot> GHC.Generics
00:13 <lambdabot> Prelude, GHC.TypeLits
00:13 <ExpHP> looks pretty good
00:14 sypwex joined
00:16 <boxscape> it is kind of funny that `(let y = \x -> x in y y) 4` works, whereas `((\y->y y)(\x->x))4` doesn't, although I understand why, I think
00:17 justicefries joined
00:17 <boxscape> :t let y = \x -> x in y y y y y y y
00:18 <lambdabot> t -> t
00:18 <boxscape> :)
00:18 <ExpHP> so my module now has 110 contiguous lines of proof
00:18 <ExpHP> https://gist.github.com/ExpHP/9b5b690ed4ffdedc0eee2dd59bbd20a6
00:18 MotherFlojo joined
00:20 <boxscape> always nice to see QED at the end
00:20 <MarcelineVQ> ExpHP: Is manual proof a requirement for you?
00:20 <ExpHP> I don't know, but I feel bad otherwise :V
00:21 <MarcelineVQ> I ask because https://hackage.haskell.org/package/checkers offers some level of checking for those laws
00:21 <CuriousErnestBro> haskell is so much fun
00:21 <CuriousErnestBro> and you guys are so nice :D
00:21 <boxscape> :)
00:21 <ExpHP> @karma+ MarcelineVQ
00:21 <lambdabot> MarcelineVQ's karma raised to -50.
00:21 <ExpHP> oh dear, -50!?
00:22 <MarcelineVQ> :>
00:22 <boxscape> guess we found the one person here who isn't nice :P
00:27 sypwex joined
00:27 jonatin joined
00:28 <reptar_> boxscape: haha :D
00:29 <reptar_> CuriousErnestBro: couldn't agree more
00:32 sypwex joined
00:33 eacameron joined
00:34 takle joined
00:36 shayan_ joined
00:40 conal joined
00:51 sypwex joined
00:53 splanch joined
00:58 takle joined
00:59 M-Sonata joined
01:03 blissdev joined
01:09 malaclyps joined
01:12 <jle`> ExpHP: btw, your Egshell is equivalent to Compose Shell (Item Line Line)
01:12 <ExpHP> wat
01:12 <jle`> data Compose f g a = Compose (f (g a))
01:12 <jle`> so, if you ever wanted a 'reference', you can look at the proofs for how Compose's instances are
01:12 <jle`> or if you get stuck on the proofs
01:13 <ExpHP> huh
01:13 <jle`> the idea is that the composition of any two Functors is itself a Functor
01:13 <jle`> and the composition of any two Applicatives is itself an Applicative
01:13 <ExpHP> I wonder if that's always the only possible applicative instance?
01:13 <jle`> it's the only Functor instance
01:14 <jle`> but it's not the only Applicative instance, I believe
01:14 <ExpHP> so yeah that's what I'd be paranoid about :P
01:15 <jle`> i think it's the only APplicative instance that lines up with the Monad instance you have, though
01:15 <ExpHP> I'm very glad to see this exists though, I know I've written my own nested functors before and thought "geez there should be a way to do this automatically"
01:15 <jle`> for any Monad instance, the Applicative is uniquely defined
01:15 sypwex joined
01:15 <jle`> (the one where (<*>) = ap, at least)
01:15 takle joined
01:15 <jle`> ExpHP: yeah, i believe that the haskellbook has writing the "nested functor" instance as an exercise
01:16 <jle`> it's actually kind of fun :)
01:16 <ExpHP> You can tell this just from looking at my implementation, or did you work this out? :P
01:16 <jle`> fmap :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
01:16 <jle`> oh i can tell from the definitino of Eggshell
01:16 <jle`> it's the composition of two functors/applicatives
01:17 <jle`> but your eggshell is unique here though from the fact that it has a Monad instance
01:17 <jle`> 'unique' as in, different from COmpose
01:17 <ExpHP> Ah
01:17 <jle`> (so sorry, I lied earlier)
01:17 <jle`> because while it is true that nested functors is a functor, and nested applicatives is an applicative
01:17 <jle`> it's not true in every case that the composition of two monads is a monad, in general
01:18 <ExpHP> You should try this trick at parties :)
01:18 <jle`> so there's no general instance for `(Monad f, Monad g) => Monad (Compose f g)`
01:18 <jle`> but
01:19 <jle`> the composition of two monads is a monad if the 'inner' one is Either e
01:19 <jle`> so `Compose f (Either e)` is a Monad whenever f is a monad
01:19 <jle`> so you're good :)
01:20 <jle`> for monads, their composition is pretty ad-hoc and there are no general rules
01:20 sypwex joined
01:20 <jle`> but this specific Monad instnace, for `f (Either e a)`, is a famous one
01:21 <jle`> it's commonly called 'ExceptT'
01:21 <ExpHP> Is that different from EitherT?
01:22 <jle`> so your type is equivalent to 'ExceptT Shell (Either u e)`
01:22 <jle`> it's the same as EitherT
01:22 <jle`> just weird historical naming differences
01:22 <jle`> um, so
01:22 <jle`> type Egshell = ExceptT Shell (Either Line Line)
01:22 <jle`> so if you want, you can just use ExceptT from transformers
01:23 <jle`> and you can skip the proofs because you trust that the maintainers of transformers provide you valid instances
01:23 <jle`> `instance Monad m => Monad (ExceptT m e)` means that "if m is a Monad, then `ExceptT m e` is also a monad. we pinky promise"
01:24 <ExpHP> I will try that out and see what happens :)
01:25 <jle`> or you can alternatively verify that your implementation is the same as the instance for ExceptT, and rest assured that your monad instance is correct :)
01:25 tom7942 joined
01:25 <ExpHP> yes that might be quicker
01:26 <jle`> ExceptT basically writes your instances for you automatically
01:26 <jle`> it also has convenient ALternative, MonadIO, and MOnadPlus instances
01:26 <jle`> for your consumption
01:26 takle joined
01:27 <ExpHP> oh wow, yep, (>>=) for ExceptT is exactly what I have
01:27 <ExpHP> knowledge is power
01:29 <ExpHP> @karma+ jle`
01:29 <lambdabot> jle`'s karma raised to 28.
01:29 <jle`> :3
01:32 systemfault joined
01:33 Youmu joined
01:34 takle joined
01:39 sypwex joined
01:44 MotherFlojo joined
01:47 louispan joined
01:48 boxscape_ joined
01:51 systemfault joined
01:52 systemfault joined
01:54 hphuoc25 joined
01:55 takle joined
01:57 takle joined
02:03 sypwex joined
02:04 aarvar joined
02:08 sypwex joined
02:15 hphuoc25 joined
02:16 <ExpHP> @%&*%@
02:16 <lambdabot> Unknown command, try @list
02:16 <ExpHP> Not you lambdaboy
02:16 <ExpHP> Looks like Eggshell is not a MonadPlus
02:17 <ExpHP> (a >> empty) for an eggshell forwards the stdout/stderr of a, then terminates
02:17 <ExpHP> but the right zero law requires (a >> empty) == empty
02:19 nomotif joined
02:21 Rodya_ joined
02:21 <ExpHP> it's interesting though, because the fact that ">> empty" terminates an Eggshell is a pretty significant feature. Aside from that one detail, I do basically use it like a MonadPlus
02:25 exferenceBot joined
02:28 smichel17 joined
02:28 splanch joined
02:29 Rodya_ joined
02:29 hexagoxel joined
02:36 aminb joined
02:36 aminb joined
02:43 tom7942 joined
02:44 dni- joined
02:45 hphuoc25 joined
02:50 MotherFlojo joined
02:50 smichel17 joined
02:51 takle joined
02:54 conal joined
02:58 marvin2 joined
02:59 takle joined
03:14 HaskellLord69 joined
03:14 <HaskellLord69> join #xmonad
03:14 <HaskellLord69> whoops
03:17 splanch joined
03:18 hphuoc25 joined
03:20 takle joined
03:37 baldfat_ joined
03:48 eacameron joined
03:49 Rodya_ joined
03:51 takle joined
03:54 splanch joined
04:03 takle joined
04:09 hphuoc25 joined
04:12 <jle`> ExpHP: for what it's worth, `(>> empty) = id` is a highly contested MonadPlus law
04:12 <jle`> er, (>> empty) = const empty
04:12 <jle`> it's not satisfied by many of the instances in base
04:12 <jle`> that's not a law i'd worry about
04:12 <ExpHP> that's a bit reassuring
04:13 <ExpHP> for my purposes I'd prefer if the law was merely that (>> empty) was idempotent
04:15 <ExpHP> ehummm well I guess that's not strong enough either
04:15 <ExpHP> I guess it's a balancing act :P
04:19 mac10688 joined
04:21 jrajav joined
04:33 dni- joined
04:33 takle joined
04:33 MotherFlojo joined
04:33 <jle`> that's an interesting law :o
04:37 eacameron joined
04:41 <HaskellLord69> im trying to do code coverage for a small project, how the heck do I generate a tix file?
04:42 takle joined
04:45 <MarcelineVQ> HaskellLord69: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/profiling.html#observing-code-coverage if you haven't seen it
04:46 <HaskellLord69> I haven't, thank you.
04:59 takle joined
05:12 splanch joined
05:13 takle joined
05:14 vaibhavsagar joined
05:21 takle joined
05:23 yellowj joined
05:26 jsoo joined
05:28 meandi_2 joined
05:36 tom7942 joined
05:41 kritzcreek_ joined
05:41 takle joined
05:43 c137 joined
05:53 Rodya_ joined
05:53 splanch joined
05:58 splanch joined
05:59 ThomasLocke joined
05:59 ThomasLocke joined
06:04 splanch joined
06:05 shayan_ joined
06:20 sypwex joined
06:22 dni- joined
06:28 takle joined
06:47 sypwex joined
06:49 zero_byte joined
06:51 sypwex joined
06:53 dni- joined
06:53 slomo joined
06:54 harfangk joined
06:56 Pupnik joined
06:59 ali_bush joined
06:59 ali_bush joined
07:06 takle joined
07:06 sypwex joined
07:12 curious_corn joined
07:21 mattyw joined
07:22 takle joined
07:23 nacon joined
07:23 nacon joined
07:24 ali_bush joined
07:24 ali_bush joined
07:27 madjestic joined
07:28 jsoo joined
07:28 splanch joined
07:32 splanch_ joined
07:38 takle joined
07:38 thc202 joined
07:46 sypwex joined
07:54 sypwex joined
07:55 Rodya_ joined
07:59 MotherFlojo joined
08:18 pie_ joined
08:18 merijn joined
08:18 takle joined
08:20 binaryplease joined
08:20 grdryn joined
08:21 Durz0 joined
08:26 binaryplease1 joined
08:28 sigmundv_ joined
08:37 takle joined
08:37 sypwex joined
08:38 nick_h joined
08:39 hphuoc25 joined
08:46 splanch joined
08:49 splanch_ joined
08:52 <reptar_> what's the difference between [Int] and IO [Int] and how do i use the latter?
08:56 Rodya_ joined
08:57 <Ferdirand> reptar_: the former is a list of ints, the latter is the description of an IO action than, when executed, will produce a list of ints
08:57 <reptar_> then my question is how to execute it
08:58 <Ferdirand> you use either a do-block or the bind operator (>>=) to bind another IO action that will make use of the result
08:58 <Ferdirand> you cannot execute it, that is the point
08:58 <Ferdirand> because haskell is pure
08:59 <Ferdirand> you can only combine it with other actions
08:59 <Ferdirand> then let the runtime execute it
09:00 <Ferdirand> maybe the easiest is with a do-block. The <- arrow will give you the impression that you take the [Int] out of IO
09:00 prophile joined
09:00 <Ferdirand> how familiar are you with these things ?
09:06 <reptar_> Ferdirand: not very
09:06 <reptar_> what i'm trying to do is this "map readInts [1..m]"
09:06 <reptar_> where readInts returns IO [Int]
09:07 <reptar_> well, i know about purity etc., it's "just" the practical implications i don't know much about yet
09:08 <reptar_> store "map readInts [1..m]" to use later*
09:09 <Ferdirand> so the type of readInts is Int -> IO [Int] ?
09:10 <reptar_> just IO [Int]
09:11 <Ferdirand> then I don't understand what you want to do with the map
09:12 <Ferdirand> repeat the action m times ?
09:12 <reptar_> yes
09:12 <reptar_> to get [[Int]]
09:13 <Ferdirand> okay, so, to stay on your track, bear with me for a minute
09:13 <Ferdirand> map would require a function that consumes whatever is being mapped, so you'd have to at least write
09:13 <Ferdirand> map (\_ -> readInts) [1..m]
09:14 <Ferdirand> or map (const readInts) [1..m]
09:14 <Ferdirand> that would leave you with an [IO [Int]]
09:14 <Ferdirand> which is a list of actions producing ints, but these actions are not being run nor composed. It's just a list of possible actions that you can take.
09:15 <Ferdirand> now, if you have a list of actions, you could use `sequence` to run them in order and produce a list of all the results
09:15 <Ferdirand> :t sequence
09:15 <lambdabot> (Monad m, Traversable t) => t (m a) -> m (t a)
09:15 <Ferdirand> ok, not the clearest signature, but it specialises to
09:15 <Ferdirand> [IO t] -> IO [t]
09:15 <Ferdirand> however, you also have mapM
09:15 <Ferdirand> :t mapM
09:15 <lambdabot> (Monad m, Traversable t) => (a -> m b) -> t a -> m (t b)
09:16 <Ferdirand> here it specialises to (a -> IO b) -> [a] -> IO [b]
09:16 <Ferdirand> so, mapM (\_ -> readInts) [1..m]
09:16 <Ferdirand> and finally
09:16 <Ferdirand> in the pure world you have replicate
09:16 <Ferdirand> :t replicate
09:16 <lambdabot> Int -> a -> [a]
09:17 <Ferdirand> which repeats a value n times
09:17 <Ferdirand> and you have replicateM, which sequences the same action n times
09:17 <reptar_> oh, but i don't want the same value
09:17 <Ferdirand> :t replicateM
09:17 <lambdabot> Applicative m => Int -> m a -> m [a]
09:18 <reptar_> readInts = fmap (map read.words) getLine
09:18 <reptar_> so each line is (very likely) different
09:18 <Ferdirand> yes, of course
09:18 <Ferdirand> with replicateM, you repeat the same action. The outcome of every action can be different.
09:19 <reptar_> ah i see
09:19 <Ferdirand> you can also use replicate to prepare your list of actions, and sequence to execute them in order
09:19 <Ferdirand> @src replicateM
09:19 <lambdabot> replicateM n x = sequence (replicate n x)
09:20 <Ferdirand> @src mapM
09:20 <lambdabot> mapM f as = sequence (map f as)
09:21 <Ferdirand> when you define readInts, there is also only one readInts
09:21 <Ferdirand> it's not a function, it's a constant
09:21 <Ferdirand> but it's a constant action, which can be run many times and have a different outcome each time
09:22 <reptar_> i still don't understand why i can't do "map f [1..m]" because it's an IO type
09:23 <reptar_> because f returns an IO type*
09:24 <merijn> reptar_: You can, but you don't end up with what you want :)
09:24 <merijn> :t map print [1..10]
09:24 <Ferdirand> :t fmap (map read.words) getLine
09:24 <lambdabot> [IO ()]
09:24 <lambdabot> Read b => IO [b]
09:24 <Ferdirand> your readInts has type IO [b]
09:24 <Ferdirand> it's not a function
09:24 <merijn> reptar_: [IO ()] is a list of IO actions, not something that performs the actual actions
09:25 <merijn> reptar_: Try the following in ghci:
09:25 <merijn> map print [1..10] !! 3
09:25 <merijn> mapM print [1..10]
09:26 MotherFlojo joined
09:27 NoCreativity joined
09:30 <reptar_> merijn: oh, i think i get it now
09:31 <reptar_> @karma+ merijn
09:31 <lambdabot> merijn's karma raised to 52.
09:31 <reptar_> @karma+ Ferdirand
09:31 <lambdabot> Ferdirand's karma raised to 3.
09:34 <merijn> reptar_: Basically, many languages have first class functions, but Haskell also has first-class IO (i.e., you can pass it around like a value), to actually get such a value to execute you need to use >>=, join, etc. to tie it into the execution of 'main' (performed by the runtime system). In this case, for example, we want to basically "combine" all the separate [IO ()] we've created into a
09:34 <merijn> single big one
09:35 <merijn> reptar_: We can use ">>" to do that, and if you're familiar with fold we can use, for example "foldr (>>) (return ())" to do that. But since that's such a common thing to do we have more convenient methods, like:
09:35 <merijn> :t sequence -- this keeps the value associated with every action
09:35 <lambdabot> (Monad m, Traversable t) => t (m a) -> m (t a)
09:36 <merijn> :t sequence `asAppliedTo` (undefined :: [IO Int])
09:36 <lambdabot> [IO Int] -> IO [Int]
09:36 <merijn> But sometimes, for example while printing, you don't even care about the list of results ([()] is kinda pointless)
09:36 <merijn> :t sequence_ -- which is why we have this
09:36 <lambdabot> (Monad m, Foldable t) => t (m a) -> m ()
09:37 <merijn> :t sequence_ `asAppliedTo` (undefined :: [IO ()])
09:37 <lambdabot> [IO ()] -> IO ()
09:37 splanch joined
09:37 <merijn> mapM and mapM_ or simply "sequence . map f" and "sequence_ . map f" for simplicity :)
09:43 arpl joined
09:43 arpl left
09:53 <reptar_> merijn: thanks :D
09:55 qu1j0t3 joined
09:56 Rodya_ joined
09:59 c137 joined
10:00 <c137> Can someone please recommend me the source to start haskell?
10:02 hphuoc25 joined
10:05 eacameron joined
10:07 splanch joined
10:09 yellowj joined
10:10 howdoi joined
10:17 mattyw joined
10:28 NeverDie joined
10:45 kritzcreek_ joined
10:51 mengu joined
10:51 NeverDie_ joined
10:58 gregman_ joined
11:01 netheranthem joined
11:02 contiver joined
11:12 jonatin joined
11:12 xmonader joined
11:13 Gloomy joined
11:16 zero_byte joined
11:39 jmg8766 joined
11:44 NeverDie joined
11:50 ederign joined
11:51 Rodya_ joined
11:57 Gloomy joined
11:57 splanch joined
11:59 splanch_ joined
12:01 splanch__ joined
12:08 galderz joined
12:15 merijn joined
12:16 splanch joined
12:16 machinedgod joined
12:18 Ferdirand joined
12:19 pie_ joined
12:19 mattyw joined
12:25 nitrix joined
12:34 hphuoc25 joined
12:35 <M-Sonata> c137, https://github.com/bitemyapp/learnhaskell/#how-to-learn-haskell
12:37 <reptar_> dem gon
12:37 MotherFlojo joined
12:40 snowcrshd joined
12:42 merijn joined
12:49 splanch joined
12:51 chlong joined
12:52 Rodya_ joined
12:59 pie_ joined
13:04 sypwex1 joined
13:06 ExpHP joined
13:10 pbrant joined
13:12 merijn joined
13:12 wei2912 joined
13:14 sypwex joined
13:20 lampam joined
13:20 jorris joined
13:21 hphuoc25 joined
13:27 mizu_no_oto_work joined
13:29 NeverDie joined
13:31 NeverDie_ joined
13:39 Uniaika joined
13:41 merijn joined
13:43 eacameron joined
13:45 snowcrshd joined
13:45 eacameron joined
13:48 kagcc joined
13:53 Rodya_ joined
13:55 galderz joined
13:56 galderz joined
13:56 earldouglas joined
14:09 guampa joined
14:09 jmg8766 joined
14:19 binaryplease joined
14:21 animated joined
14:22 conal joined
14:26 grdryn joined
14:26 vmeson joined
14:28 <reptar_> merijn: i'm still not getting anywhere http://lpaste.net/6399994633933291520
14:28 <reptar_> pointers?
14:29 <merijn> reptar_: sequence doesn't do anything there
14:29 <merijn> At least, not what you want it, I think
14:30 <merijn> So you want to read m lines and read many ints per line, yes?
14:30 <reptar_> yes
14:31 <reptar_> i want a [[Int]] with m [Int] elements
14:32 <merijn> Do you want to print one num per line? or multiple numbers per line?
14:33 <lpaste_> merijn annotated “No title” with “Simplified!” at http://lpaste.net/6399994633933291520#a353973
14:34 <merijn> reptar_: Look at that
14:34 <merijn> forM is awkward to use for what you want
14:34 <merijn> :t replicateM
14:34 <lambdabot> Applicative m => Int -> m a -> m [a]
14:34 <reptar_> i want to construct a [[Int]] to pass to "relation" and print out "YES" or "NO" for each m
14:36 <merijn> reptar_: You read a number 'm' and then you want to, 'm' times read a number 'n' and then read 'n' lines of numbers, no?
14:37 <merijn> Your current pseudo-code would end up in [[[Int]]], I
14:37 <merijn> i.e. m lists of n lists of lists of Int
14:37 <merijn> Since you're currently reading more than one number per n lines
14:38 MotherFlojo joined
14:40 <reptar_> i want to read a number n, read a number m and read m lines n times
14:41 <merijn> reptar_: Right, but now you'd reading multiple Int per lines
14:41 <reptar_> yes
14:41 <merijn> oh, wait
14:41 <merijn> Then your initial sketch was wrong, since you were reading 'm' inside the loop
14:42 <merijn> reptar_: Right, but then you'd end with [[[Int]]], not [[Int]], no?
14:42 <merijn> Since the outer list correspond to 'n' and the middle list to 'm', which leaves [Int] for the ints on a line
14:42 <reptar_> no
14:42 <reptar_> no outer list
14:43 <lpaste_> merijn revised “Simplified!”: “Simplified!” at http://lpaste.net/353973
14:43 <merijn> reptar_: Sounds like you basically want that
14:44 <merijn> Actually, you probably want replicateM_ for the outer one
14:44 <merijn> But other than that
14:44 <reptar_> oh, maybe i do
14:45 <merijn> (replicateM keeps the results of repeating an action X times, replicateM_ throws them away)
14:51 <reptar_> i change my mind, i don't need an outer list
14:51 <Akii> kinda not liking how this turned out http://lpaste.net/353975
14:51 <reptar_> because i can just print "YES" or "NO" for each loop
14:52 splanch joined
14:53 Rodya_ joined
14:55 <Akii> currently thinking of what would happen if you'd call this twice with different `c`s http://lpaste.net/353975#line75
14:55 <Akii> too many side effects xD
14:56 uglyfigurine joined
15:00 <reptar_> merijn: ay, the problem is that i can't map IO [Int] to [Int]
15:01 <reptar_> in "map readInts [1..m]"
15:02 jomg joined
15:03 <reptar_> what was i thinking
15:11 geekosaur joined
15:14 takle joined
15:18 mengu joined
15:23 blissdev joined
15:24 carlomagno joined
15:26 chlong joined
15:39 geekosaur joined
15:40 geekosaur joined
15:43 Gloomy joined
15:48 tangled_z joined
15:49 skeet70 joined
15:51 <reptar_> merijn: http://lpaste.net/7670403633187389440
15:51 <reptar_> it was so simple *facepalm*
15:55 <nitrix> Akii: Oh yeah, `c` is phantom, right?
15:55 <Akii> nope
15:58 conal joined
15:58 jmiven joined
15:58 <nitrix> Mhh, I see. Your whole module is just a wrapper around Map.
15:58 <Akii> yup
15:58 <Akii> just a Map of concurrent IO actions
15:59 <nitrix> Line 98, gotcha.
15:59 <Akii> yup
15:59 <Akii> some stuff is still missing obviously
16:00 <nitrix> Why does the user gets the ProjectionId ?
16:00 <Akii> the IO actions must be able to report new state
16:00 <Akii> that's just the name of the projection
16:00 <nitrix> Ah yeah it is the key.
16:00 <nitrix> I'm starting to get this :D
16:00 <Akii> haha ^^
16:00 <Akii> ye, bad code
16:01 <Akii> but hey, works
16:01 <nitrix> Let's thinking what happens with 81 for different `c`s ...
16:01 <nitrix> Or 75.
16:01 <Akii> `c` is also where each projection will keep its state
16:02 <Akii> might want to separate c (Config) from the state
16:03 <nitrix> Akii: Maybe what you need is just not being able to start a projection that's already started ?
16:04 <Akii> that would make stuff pretty inconsistent atm
16:04 <nitrix> Are these the effects you're worried about? I see you're stopping the old projection if that happens :P
16:05 <Akii> lots of stuff is wrong with that implementation atm ^^
16:05 <Akii> restarting the projection at least makes it somehow consistent
16:08 Deide joined
16:08 geekosaur joined
16:09 geekosaur joined
16:11 <Akii> ye, I'll separate config from projection output
16:11 <nitrix> Akii: At the same time, even though it describes effects a little too losely, at least now you have a Projection type to use around in your code to distinguish what's happening. `Projection TopDown`, `Projection Isomeetric` etc.
16:11 <Akii> and then hide that a bit
16:13 geekosaur joined
16:13 <Akii> a sum type to go along with that `data Foo = F { topDown :: TopDown, isometric :: Isometric }`
16:14 <nitrix> foo :: ProjectionM c; foo = do { startProjection "bar"; stopProjection "baz" }
16:14 <Akii> then some morphism
16:14 <Akii> probably not going to need that
16:14 <Akii> actually
16:14 <nitrix> I think a monad would be nice, hiding some state or something
16:14 <nitrix> startProjection :: c -> Projections c -> ProjectionId -> IO (Projections c)
16:15 <nitrix> I don't like that it's returning the very argument that it needs, and that someone can entangle themselves with the previous and newer states accidently.
16:15 <Akii> ye absolutely
16:15 <Akii> the fact that this returns a new list is strange
16:16 <nitrix> Akii: startProjection :: c -> Projections c -> ProjectionId -> Projector ()
16:16 geekosaur joined
16:16 <Akii> so the ultimate goal is of course to get access to the projection state
16:17 <nitrix> I'm scratching my head over how to turn `Projections c` into `Projections`.
16:17 <nitrix> The problem is the async async in the end is `:: c -> Async ()`.
16:17 hphuoc25 joined
16:18 <Akii> foo :: ProjectionM c; foo = do { startProjection "bar"; stopProjection "baz" }
16:18 <Akii> that needs `getProjectionState "bar"`
16:19 <nitrix> That might lead to existantial quantification though; putting a constraint on a ProjectorConfig typeclass just to remove that `c` parameter is a little odd.
16:19 <nitrix> But it'd be so nice because now the Projector is the one that'd be configured, rathed than each operations.
16:19 sypwex joined
16:19 <nitrix> Akii: startProjection :: Projections -> ProjectionId -> Projector c ()
16:20 <nitrix> The only problem with this is that the monad can only deal with projections that are all processed with the same configuration.
16:20 <nitrix> Which is what you wanted I think?
16:21 geekosaur joined
16:21 <Akii> that would make sense
16:22 <Akii> because usually you want one set of projections defined in one place
16:22 <Akii> idk
16:22 <Akii> this maybe a candidate for an hlist
16:22 <Akii> for the state of each projection
16:22 <Akii> or.. state monad
16:22 <Akii> each of these projections updates some state
16:23 <nitrix> Akii: Is this going to be part of a open-source project? I wonder if we can clean it up.
16:23 <Akii> nope, closed source
16:23 <Akii> but one could generalize this to just io actions
16:24 <nitrix> newtype Projector config result = Projector { runProjector :: StateT config IO result }
16:24 <Akii> ye, hm
16:24 <Akii> maybe
16:24 <Akii> too specific
16:24 <Akii> could also project into a database
16:25 <Akii> I've to put in more thought
16:25 <nitrix> What's the project :3 ?
16:25 splanch joined
16:25 <Akii> nothing released yet ^^
16:26 <nitrix> Getting a sandwich then I'll launch a collaborative coderpad and try to fiddle around with the Projector idea with you c:
16:26 <Akii> kay :D
16:28 tom7942 joined
16:29 geekosaur joined
16:38 sypwex joined
16:39 MotherFlojo joined
16:43 Rodya_ joined
16:47 splanch joined
16:48 <nitrix> Akii: https://coderpad.io/CA2FNEWQ
16:51 jorris joined
16:53 pie_ joined
16:56 <nitrix> Akii: Weew, it compiles!
16:57 <nitrix> Akii: That'll be a pain to test there with the multithreaded stuff. Hold on :P
16:59 <Akii> re
16:59 <Akii> nitrix: :D
16:59 <Akii> nice editor thingy
16:59 <nitrix> Akii: It doesnt support other libraries so I had to change Text to String and ClassyPrelude to Prelude
16:59 <nitrix> and aysnc with control.concurrent
16:59 <nitrix> Even then we can't test concurrency it's pretty horrible
16:59 <nitrix> I have a better alternative
17:01 <nitrix> Or not, now they're a paid service.
17:02 <nitrix> Erf.
17:02 <Akii> lel
17:02 <nitrix> I'll just mockup code
17:03 <nitrix> Akii: Oh god
17:04 <nitrix> Akii: Your async tasks are themselves modifying the config?
17:04 <Akii> yup
17:04 <Akii> although that part is debatable
17:04 <nitrix> Akii: How do you ensure they are ran in the proper order?
17:04 <Akii> it depends on how the state is later queried
17:04 mac10688 joined
17:04 <nitrix> To not create race conditions?
17:04 <Akii> one projection writes to one IORef in the config
17:05 <Akii> I see no problem there
17:05 <Akii> the actual question is getting the state out
17:05 <nitrix> Yeah but if you have 5 projections, they will all have the same config wont they?
17:05 <Akii> so if you have a projection that writes a SQL database there is no need to write anything in the config
17:05 yellowj joined
17:06 <nitrix> Akii: Shouldn't it be more like...
17:06 <nitrix> Akii: projection :: c -> IO (Maybe c) ?
17:06 <Akii> nope
17:06 <nitrix> Or even better
17:06 <nitrix> StateT config IO ()
17:06 <nitrix> This way, from the projection point of view, it can get the state and modify the state
17:07 <Akii> that's what I meant with I need to think about it more
17:07 <nitrix> But from the /projector/ point of view, it only gets a final state which is created by the IO ?
17:07 <nitrix> RIP coderpad.
17:08 <Akii> ye
17:08 <Akii> :D
17:08 <Akii> funny guy
17:08 <Akii> there is no final state
17:10 <Akii> thats what you get for processing an infinite stream of events ^^
17:10 <nitrix> I think with your design, the best you can have is eventual consistency, possibly a race condition.
17:10 <nitrix> Depending what these projections do
17:11 hoffmeyer joined
17:11 pilne joined
17:11 <nitrix> The cool thing with Haskell is that you could actually model and support both with a few type trickery
17:12 <Akii> if each projection would define how to get the state, it'd be optimal
17:12 <nitrix> I don't know, otherwise it's a lot of power given to the guy creating projections to not fuck up :P
17:12 <Akii> which is me so np
17:12 <nitrix> Akii: make projection :: StateT state IO () ?
17:12 <Akii> fun how exploration leads to new insight
17:13 <Akii> nitrix: sure and how does state look like for projections writing to a DB
17:13 <nitrix> Oh nvm you wanna share the state
17:13 NeverDie joined
17:13 <Akii> you'd need a way to also run queries against the DB
17:13 <Akii> those are well defined ususally
17:13 <nitrix> I don't have the full picture so it's a little harder for me
17:14 Gloomy joined
17:14 <Akii> so the state would be smth like `findByIdentifier :: Text -> IO (Maybe SomeResult)`
17:14 <Akii> instead of just being `SomeState`
17:14 <Akii> and that depends on the projection itself
17:17 tlax joined
17:19 <Akii> basically a projection must do 2 things: 1 do its projection, whatever that is - all we know is IO (); 2 provide a defined way of getting the state
17:19 <Akii> that sounds usable
17:21 <nitrix> data Projection = Projection { runProjection :: IORef s -> IO (); getState :: IORef s -> s }
17:21 <nitrix> Akii: If the projection receives a reference, you already have a way to obtain to state.
17:22 <nitrix> Akii: getState becomes redundant.
17:22 <nitrix> data Projection s = Projection { runProjection :: IORef s -> IO (); getState :: IORef s -> IO s }
17:22 <Akii> yup
17:23 <nitrix> Sorry, that one is a little more type correct.
17:23 aarvar joined
17:23 <Akii> can't do anything with an IORef s without the return type being IO xD
17:23 <Akii> yes, smth like that
17:23 <Akii> for in-memory projections this gives you the state directly
17:23 <nitrix> Unless you're a masochist that understands memoization very well.
17:23 <Akii> for database projections this would just give you a data type with query methods
17:24 <Akii> the database projection would never update its state but update the DB
17:24 <Akii> now the fun part is sticking those projections in a map
17:25 <nitrix> Akii: Is you problem that you can only store projections of the same type in your map?
17:25 <Akii> s yep
17:25 <Akii> -s
17:25 <nitrix> Akii: But you'd want different types because all you care is storing the "id" and the Async () computation?
17:25 <nitrix> Akii: https://hackage.haskell.org/package/base-4.9.1.0/docs/Data-Dynamic.html
17:26 <Akii> I can simply use functors to turn Projection A, Projection B into Projection (A and B)
17:27 <Akii> and then I can stick them into the same map again
17:27 <nitrix> Akii: The module lets you convert anything `Typeable t => t` to a Dynamic, then Dynamic back to `Typeable t => Maybe t`, assuming the compiler is able to infer what the type wanted is.
17:27 <Akii> I guess
17:27 <Akii> that looks like magic to me
17:27 <Akii> unnecessary magic
17:27 <nitrix> Then I'm lost. I don't know what you want x]
17:28 snowcrshd joined
17:28 truelean joined
17:29 <Akii> getState :: Projections s -> ProjectionId -> IO a
17:29 <Akii> that looks weird
17:29 <Akii> and unsafe af
17:30 <Akii> getState :: Projections (A and B) -> ProjectionId -> IO A
17:30 <Akii> probably a bad idea
17:30 <Akii> I'll probably use something more type-safe
17:31 <Akii> there is no need for the ProjectionId here anyway
17:31 <Akii> the state is well known
17:31 <nitrix> Now that sounds like GADTs.
17:31 <Akii> it compiles in my head
17:31 <nitrix> :P
17:31 <Akii> let me fiddle around a bit
17:32 <nitrix> I'm working on something fun with Dynamic :P
17:33 <Akii> probably going to sprinkle in a monoid too
17:33 <Akii> that way `IORef s` has mempty
17:33 <Akii> or maybe not
17:34 delexi joined
17:38 Ferdirand joined
17:38 chlong joined
17:45 \Mike joined
17:46 sypwex joined
17:47 drewr joined
17:47 conal joined
17:48 binaryplease joined
17:49 skeet70 joined
17:49 sypwex1 joined
17:50 nacon joined
17:50 nacon joined
17:54 malaclyps joined
17:54 pie_ joined
17:58 conal joined
18:03 sypwex joined
18:08 emmanuel_erc joined
18:10 Rodya_ joined
18:10 NeverDie joined
18:15 galderz joined
18:19 zero_byte joined
18:21 malaclyps joined
18:35 jorris_ joined
18:36 Zialus joined
18:40 MotherFlojo joined
18:41 curious_corn joined
18:43 sigmundv_ joined
18:49 sypwex joined
18:49 MotherFlojo joined
18:49 peterbecich joined
18:52 Gurkenglas_ joined
18:53 sypwex joined
18:56 <nitrix> Akii: Funny, if I make > mean relation (my data type) and o mean relational (my monad), I get (>.o) :: Relation a -> (a -> Relation b) -> Relational b
18:57 <nitrix> Akii: Similarly, (>.>) isn't possible.
18:57 <nitrix> Akii: Since the Relational monad is needed to resolve the Relation.
18:59 sypwex joined
19:00 drewr joined
19:01 yellowj joined
19:05 Zialus joined
19:05 guampa joined
19:24 jorris joined
19:27 curious_corn joined
19:28 isacloud joined
19:28 mengu joined
19:29 malaclyps joined
19:31 Purlox joined
19:33 albertus1 joined
19:36 marvin2 joined
19:39 drewr` joined
19:41 drewr` joined
19:41 codedmart joined
19:42 ekinmur joined
19:46 pie_ joined
19:57 nick_h joined
19:57 sypwex joined
20:00 mojjo joined
20:10 sypwex joined
20:13 dni- joined
20:15 curious_corn joined
20:18 thallada joined
20:20 sypwex joined
20:22 Rodya_ joined
20:24 curious_corn joined
20:24 qu1j0t3 joined
20:28 Rodya__ joined
20:29 ExpHP joined
20:30 azahi joined
20:31 MotherFlojo joined
20:34 sypwex joined
20:42 galderz joined
20:46 MotherFlojo joined
20:53 Cydo joined
20:54 jarshwah joined
20:54 delexi joined
20:54 ExpHP_ joined
20:57 Cydo left
20:58 sypwex joined
21:01 jarshwah joined
21:06 thallada joined
21:08 t0by joined
21:11 jathan joined
21:13 tangled_z joined
21:19 takle joined
21:22 sypwex joined
21:24 mac10688 joined
21:27 sypwex joined
21:42 yellowj joined
21:43 shayan__ joined
21:46 sypwex joined
21:52 hiratara joined
21:54 contiver joined
21:56 sypwex joined
21:58 splanch joined
22:02 dni- joined
22:05 guampa joined
22:10 sypwex joined
22:16 splanch joined
22:18 louispan joined
22:24 galderz joined
22:28 conal joined
22:30 ExpHP joined
22:31 hiratara joined
22:34 sypwex joined
22:36 geppettodivacin joined
22:37 malaclyps joined
22:55 mojjo joined
22:58 tangled_z joined
23:01 suls joined
23:11 louispan joined
23:28 zero_byte joined
23:51 dni- joined
23:52 splanch joined
23:54 splanch_ joined