<    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 <jle`> looks like a specific case of newtype NatTrans f g = NT (forall a. f a -> g a)
00:00 cschneid_ joined
00:00 moookle joined
00:00 <moookle> whats a good hashmap library for haskell?
00:01 <robkennedy> Maybe... Does that allow `NT typeRep`?
00:01 <moookle> or is there a builtin hashmap structure?
00:01 <jle`> moookle: there's unordered-containrs if you want actual *hash* maps
00:01 <jle`> but Data.Map from containers is the typical map structure
00:01 <jle`> key-value dictionary
00:01 pizza_before_ctf joined
00:02 <jle`> robkennedy: how is typeRep similar to listToMaybe ?
00:02 <moookle> oh is Data.Map not a hash map?
00:02 <dmwit> Hash maps turn out to be surprisingly hard to make both ephemeral and efficient, which turn out to be key ingredients for idiomatic use.
00:02 <jle`> moookle: it's map that's not implemented using hashing
00:02 <dmwit> Data.Map is uses a balanced search tree.
00:02 <kadoban> No, it's a comparison-based ordered dictionary. (something like a BST-backed)
00:02 pizza_before_ctf left
00:02 <moookle> oh I see
00:03 <moookle> dmwit: what do you mean 'ephemeral'?
00:03 <jle`> but i'm mentioning it because ruby uses the word "hashmap" to refer to key-value dicts in general
00:03 <jle`> so i suspect yuo might actually just want a map
00:03 <jle`> with a map API
00:03 <robkennedy> jle': how is it not? Rather than our ListToMaybe family, you'd have a `Const TypeRep` or similar
00:03 <kadoban> This is fairly typical, for example std::map in C++ is a BST-based ordered dictionary.
00:03 <moookle> jle`: yeah just a map
00:03 Levex joined
00:03 <jle`> typically you'd use Data.Map for this
00:03 <moookle> jle`: is containers like the standard haskell library for collections?
00:04 conal joined
00:04 <jle`> yeah, it's actually used to ghc
00:04 <jle`> *used by ghc
00:04 <dmwit> moookle: "Ephemeral" means that you can roll back to any earlier version of the data structure for free.
00:04 <moookle> ok cool :)
00:04 subttle joined
00:04 <geekosaur> ordered collections. there's also unordered-containers which is standard hash-based collections
00:04 theDon_ joined
00:04 <jle`> moookle: and it's also where the most effort goes into optimization
00:04 <jle`> dmwit: do you mean ... persistent?
00:04 <dmwit> Perhaps I mean persistent.
00:05 <jle`> because ephemeral means the opposite of that
00:05 mysticjohn joined
00:06 <jle`> robkennedy: what type family are you talking about?
00:06 <jle`> :t typeRep
00:06 <lambdabot> forall k (proxy :: k -> *) (a :: k). Typeable a => proxy a -> TypeRep
00:06 <jle`> :t listToMaybe
00:06 <lambdabot> [a] -> Maybe a
00:06 <jle`> hm yeah i suppose you could do NT (Const . typeRep) :: NatTrans p (Const TypeRep)
00:07 <dmwit> robkennedy: I suspect you'll be in for a lot less pain if you avoid heterogeneous collections, too. =)
00:07 <jle`> but actually, there has been some talk about a typerep type that is parameterized by the type
00:07 halogenandtoast joined
00:08 mwilly joined
00:08 rkazak_ joined
00:08 <robkennedy> dmwit: well my current research goal is to improve our situation on that front - I think it's within reach.
00:08 cheater joined
00:09 <jle`> oh wait, you can't do that beucas eit requires a constraint
00:10 <robkennedy> jle': yeah, the general point I think holds is that you can write a type function TF for any function f so that `f :: a -> TF a`
00:10 Guest62183 joined
00:10 <robkennedy> Switch those predicates; for any function f you can write a TF
00:11 conal joined
00:11 uncertainty joined
00:12 kubuntu_ joined
00:12 <jle`> how does that fit into typeRep?
00:12 mysticjohn joined
00:13 sellout- joined
00:13 <jle`> typeRep is `Typeable a => f a -> TypeRep`
00:13 <robkennedy> TF _ = TypeRep
00:14 <jle`> you could naively just wrap up that function, but, i'm not sure if it'll help you any heh
00:14 tag joined
00:14 louispan joined
00:14 <robkennedy> Okay you're right, you need a constraint for typeRep - I have a different solution for those solved, I was considering typeRep unconstrained
00:15 <jle`> and also 'TF _ = TypeRep' doesn't really let you do anything special for listToMaybe
00:15 mysticjohn joined
00:15 <jle`> listToMaybe :: [a] -> Maybe a
00:15 <robkennedy> It's a different TF for each function, if that weren't clear.
00:15 <juri_> http://implicitcad.org/ now working properly again. :)
00:16 <jle`> yeah, using NatTrans, you can parameterize it based on the type functions/constructors
00:16 <jle`> you can require a constraint too by parameterizing on the constraint
00:16 <pacak> Any ideas how to make some code that will load fine in ghci but will fail to compile?
00:16 <robkennedy> I'll hit that.
00:16 <jle`> newtype NatTrans c f g = NT (forall a. c a => f a -> g a)
00:17 <jle`> this should still form a category I believe
00:17 yellowj joined
00:17 <jle`> the original form would just have 'c' be the always-satisfied constraint
00:17 <jle`> type NoConstraint a = () :: Constraint
00:17 <robkennedy> Ummm does `NatTrans head` or `NatTrans (:[])` typecheck?
00:18 <jle`> you'd need to explicitly go thorugh the identity functor
00:18 <robkennedy> Sorry, `NT head`
00:18 <robkennedy> Ah, okay. That's not too bad.
00:18 <jle`> NT (I . head) :: NatTrans c [] I
00:19 <jle`> newtype I a = I { getI :: a }
00:19 <jle`> (which is also Identity from Data.Functor in base)
00:19 <jle`> NT ((:[]) . getI) :: NatTrans c I []
00:20 <dmwit> pacak: Sure, just don't put `main`. ;-)
00:20 <jle`> NT (Const . typeRep) :: NatTrans Typeable p (Const TypeRep)
00:20 tromp joined
00:20 <pacak> dmwit: There is no main, but a few things are exported.
00:20 Rizy joined
00:20 Rodya_ joined
00:20 hsk3 joined
00:21 ystael joined
00:21 wtetzner joined
00:21 <dmwit> pacak: I suddenly feel lost.
00:21 <robkennedy> Okay, that's pretty much the abstraction I was looking for. The wrap into Identity is not terrible. I appreciate it
00:21 safe joined
00:21 <dmwit> pacak: Your first question was about how to write some new code. Your followup refers implicitly to some existing code. Can you help connect these two comments for me?
00:22 <jle`> instance Category (NatTrans c) where id = NT Prelude.id; NT f . NT g = NT (f Prelude.. g)
00:22 <pacak> dmwit: It's a module, it contains a bunch of stuff that's exported to be used in different modules
00:22 <hsk3> (/) :: Fractional a => a -> a -> a
00:22 <hsk3> 2 :: Num t => t
00:22 <hsk3> If 2 is only Num, why can I do "2 / 2"? 2 is not Fractional.
00:22 <hsk3> This seems like magic to me. If something implements Num, does it automagically also implement Fractional?
00:22 <jle`> hsk3: 2 is not only Num
00:22 <jle`> Num is not a type, anyway
00:22 <pacak> The goal is to avoid getting debugging-only code to compile
00:22 <jle`> hsk3: if 2/2 :: Double
00:23 <jle`> then 2 can be Double, which is an instance of Num
00:23 Ayey_ joined
00:23 <jle`> if you :i Double in ghci, you will see that Double is an instance of the Num typeclass
00:23 asmyers joined
00:23 <jle`> so (2 :: Double) is perfectly fine
00:23 <dmwit> pacak: Ah! You don't mean "write code which works in ghci, but causes a compile error", you mean "write code which does something in ghci but gets compiled to a no-op".
00:23 theorbtwo joined
00:23 <jle`> Double is also an instance of Fractional, so you can use '/' with it
00:23 <dmwit> pacak: CPP seems like a reasonable way to do this.
00:23 takle joined
00:24 <pacak> dmwit: More like get's compiled into big nice "don't do that dumbass" ghc error
00:24 <dmwit> pacak: -D something special when compiling but not when loading with ghci (or vice versa).
00:24 <jle`> if __main__ == "__main__" ...
00:24 ali_bush_ joined
00:24 <pacak> And talking about CPP - that's the reason I'm worried
00:24 <pacak> Code uses unboxed tuples and other magic that is not very ghci friendly so there are two versions and it gets switched with ghci
00:24 <pacak> with CPP
00:25 ramzifu joined
00:25 ffilozov joined
00:25 <jle`> hsk3: not all things that implement Num implement Fractional
00:25 <jle`> hsk3: but all things that implement Fractional implement Num
00:26 <Xnuk> @src Fractional
00:26 <lambdabot> class (Num a) => Fractional a where
00:26 <lambdabot> (/) :: a -> a -> a
00:26 <lambdabot> recip :: a -> a
00:26 <lambdabot> fromRational :: Rational -> a
00:26 <pacak> Are there any -D that ghc defines during normal compilation?
00:26 plutoniix joined
00:28 <lyxia> the compiler version probably
00:28 <lyxia> pacak: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/phases.html#standard-cpp-macros
00:28 <jle`> pacak: if you getProgName, then you can tell if something is loaded in ghc or not
00:28 <jle`> but this happens at runtime
00:29 <jle`> maybe you can use getProgName in a TH splice
00:30 <jle`> this is almost certainly a bad idea
00:30 <pacak> It is :(
00:32 <freeside> https://downloads.haskell.org/~ghc/master/users-guide/bugs.html#bugs-in-ghci-the-interactive-ghc
00:32 <geekosaur> hsk3, this is not OOP subtyping. Num specifies the *maximum* available interface; if all you have is a Num constraint, you cannot assume that anything else is available
00:33 Levex joined
00:33 <dmwit> geekosaur: I find this sentence deceptive and possibly untrue.
00:33 <geekosaur> could you expand on that?
00:34 <dmwit> If I give you a value of type `forall a. Num a => a`, you can assume much more than just `Num`. You can pick a specific `Num` instance and assume everything you know about that instance.
00:35 <geekosaur> actually I misread hsk3's comment and they were talking about the opposite situation. but yes, I was not talking about that situation
00:35 <geekosaur> I will be hyperpedantic to the point of incomprehensibility like a perl 5-er from now on.
00:35 <dmwit> I'm not encouraging that. But sloppy has its own pitfalls.
00:36 <geekosaur> ...or just not bother since comprehensibility is not one of the goals here apparently
00:36 <c_wraith> geekosaur, we just call that "precise" :)
00:36 <hsk3> When a generic function is actually called, all the generic type parameters have to be concrete types, right?
00:36 <dmwit> What is a generic function?
00:36 <freeside> ${^PEDANTRY} = 65535;
00:36 <jle`> s/generic/polymorphic, but yeah
00:36 <jle`> generic is a Java term
00:36 <hsk3> Ok. Now.
00:36 <hsk3> When I do 2 / 2, what does 2 turn into? Double?
00:37 <jle`> it depends on what you want the result to be
00:37 <dmwit> That depends. In ghci, by default, yes.
00:37 takle joined
00:37 andyhuzhill joined
00:37 <jle`> if there are no other clues the ghc will make a guess and assume you mean Double, but this is sort of an ad-hoc thing
00:37 <geekosaur> oh, so I described the oposite condition to yours (covariance vs. contravariance, roughly), and if I am permitted...
00:37 <jle`> > 2 / 2 :: Float
00:37 <freeside> when you do 2 / 2, it doesn't turn into Double. it turns into Half! ha, ha.
00:37 <lambdabot> 1.0
00:37 <dmwit> I'm not sure I'm on board with "when a polymorphic function is actually called, all the type variables have to be concrete types", by the way. But it might be a decent first approximation for now.
00:38 <robkennedy> hsk3: but if you define a different type which is Fractional and Num, it could be that. If you turn on Wall you will be told more about this
00:38 <hsk3> But if it's Double by default, why is the result a generic Fractional?
00:38 <hsk3> Prelude> let b = 2 / 2
00:38 <hsk3> Prelude> :t b
00:38 <hsk3> b :: Fractional a => a
00:38 <geekosaur> the case (2 :: Num a => a) means that the compiler knows how to generate that value at any Num instance type (by applying fromInteger; Num instances must provide this)
00:38 <jle`> hsk3: polymorphic
00:38 <jle`> but that's because there are no other clues
00:38 <jle`> so b can be *any* instance of Fractional you want
00:38 <geekosaur> (/) requires a Fractional instance, so that constrains what Num instances are permitted
00:38 <jle`> do you want it to be a Double? you got it! if you want it to be Float, that's ok too!
00:39 <geekosaur> then defaulting leads ghc to pick Double as the type
00:39 <jle`> do you want it as a Rational? knock yourself out :)
00:39 <jle`> ghci keeps polymorphic bindings polymorphic
00:39 <jle`> b could be *any* instance of Fractional that you want
00:40 <jle`> defaulting doesn't happen in ghci by default, but it happens in haskell source code for performance reasons
00:40 <dmwit> hsk3: Now you see why I was not on board with "when a polymorphic function is actually called, all the type variables have to be concrete types".
00:40 <geekosaur> jle`, um
00:40 louispan joined
00:40 <geekosaur> defaulting does happen because it compute it it needs to know the type
00:40 <freeside> ghci: Keepin' It Classy[tm]
00:40 <dmwit> hsk3: In fact, when a rank-1 polymorphic function is called, all the type variables have to be made monomorphic. But they may not be concrete types.
00:40 <jle`> oh, yeah
00:40 <geekosaur> monomorphic bindings don't happen in ghci by default
00:40 <jle`> only when you eventually want it as a monomorphic type
00:40 systemfault joined
00:41 <jle`> that is true
00:41 <jle`> defaulting happens like normal. monomorphization doesn't happen like normal
00:41 <dmwit> hsk3: And in this case, they are made monomorphic with *other type variables*; then those other type variables are re-generalized to make the whole computation polymorphic.
00:41 tommd joined
00:42 <geekosaur> this makes a bit more sense when you understand what is going on behind the scenes: a (Num a) constraint means that the compiler must provide a dictionary containing the Num instance methods for whatever type a is at the call site
00:42 <dmwit> This is made significantly more confusing by the fact that Haskell tries to hide the difference between `forall a. a` and `a` from the user.
00:42 <geekosaur> likewise (Fractional a)
00:43 prab97 joined
00:44 <geekosaur> (except it's the methods for the Fractional instance, and that includes the dictionary for (Num a) as well)
00:44 <hsk3> The above confuses me. I don't fully understand it.
00:44 <hsk3> This is why I've the habit of always doing "default ()".
00:44 <hsk3> It allows me to ignore these complexities and just specify the type I want, e.g., (2 :: Integer).
00:45 <geekosaur> in standard Haskell it would also have dictionaries for Show and Eq but ghc doesnt so that any more
00:45 <hsk3> What is your opinion of doing this?
00:45 plugin joined
00:45 <dmwit> hsk3: The latter is fine and encouraged. The former is unusual.
00:45 prab97 left
00:45 skapazzo joined
00:45 <hsk3> dmwit what's the former?
00:46 <dmwit> hsk3: Adding type signatures to fix types is fine and encouraged. Removing the defaulting rules is unusual; but you might like -XNoMonomorphismRestriction, which is common and encouraged.
00:46 <geekosaur> actually turning off defaulting can get you in trouble, because you can't always specify what typeclass instance you want in a situation involving other typeclasses
00:46 FullyFunctional left
00:46 <geekosaur> (unless you enable TypeApplication and use @ to specify)
00:46 xaviergmail_ joined
00:47 nakal_ joined
00:48 systemfault joined
00:48 <hsk3> An ordinary Haskell book for normal people won't suffice to get this.
00:48 <hsk3> I'm going to have to read the Haskell Report :S
00:48 <geekosaur> especially in ghci since it uses ExtendedDefaultRules; I think with normal defaulting you always have a way to specify in the case of the few typeclasses that defaulting works with
00:48 YongJoon joined
00:49 <geekosaur> somehow people manage to get it... as I said it makes more sense if you understand that a typeclass constraint is a dictionary passed around
00:50 <geekosaur> you have exactly what that dictionary says you have
00:51 <dmwit> hsk3: I'd be glad to explain further, but at the moment I believe I've lost track of your concrete questions.
00:51 <hsk3> I'm going to have digest all of the above and get back to you later. Thank you all!
00:51 <geekosaur> this also covers dmwit's case of a (forall a. Num a): it could be any Num instance, but all you can know about it is the Num instance. (also, yes this means it is actually a function, not a value! the compiler must pass it a typeclass dictionary to get a value)
00:51 <ricky_clarkson> If you're used to thinking in Java or similar, here's something I wrote explaining it: http://rickyclarkson.blogspot.com/2009/01/typeclass-pattern.html
00:51 aib joined
00:51 aarvar joined
00:52 <geekosaur> Haskell compilers try to hide this, but => looks a bit like -> for a reason; it really does represent an extra parameter, just not one you can supply or manipulate except by changing the signature
00:52 louispan_ joined
00:53 markus1189 joined
00:53 markus1199 joined
00:53 <geekosaur> (barring some evil which I believe dmwit has experience with :)
00:53 <dmwit> =)
00:54 <dmwit> Also worth mentioning that many of the comments here are GHC-specific. Other compilers implement typeclasses in other ways.
00:54 <dmwit> But dictionary-passing is a pretty good way to understand it, not least because GHC is absolutely the most-used compiler.
00:57 heurist joined
00:57 <geekosaur> also because (at least I'm under the impression that) the original Report specification of typeclasses was geared toward a simple dictionary-passing implementation, to make life easier for compiler writers
00:58 <geekosaur> (what ghc can do with typeclasses is much more than the Report specifies, but that just means not the simplest possible dictionary passing impl)
00:59 muesli4 joined
01:00 conal joined
01:01 mu_ joined
01:02 robertkennedy joined
01:02 lambda-11235 joined
01:04 Big_G joined
01:04 faberbrain joined
01:04 anuxivm left
01:06 subttle joined
01:07 eschnett joined
01:09 nighty- joined
01:13 b4ff3r joined
01:13 robkennedy joined
01:13 cschneid_ joined
01:14 Ayey_ joined
01:15 prab97 joined
01:16 justicefries left
01:20 andyhuzhill joined
01:21 sanett joined
01:22 wtetzner joined
01:22 ystael joined
01:23 buttons840 joined
01:26 <jchia_> I'm trying to build a graph at compile-time and using it at run-time to traverse the nodes in a specific order (a node can be visited only if it has no unvisited predecessor). I specify a node with a unique string name and an arc by providing the names of the nodes. Currently, I'm building it at runtime, so if I misspell a node name when adding an arc, I get a run-time error. How can I build the graph at compile-time so that such errors
01:26 <jchia_> are compile-time errors?
01:29 HoierM joined
01:29 FreeBirdLjj joined
01:32 Stanley00 joined
01:33 <Cale> jchia: Well, perhaps you could at least choose a different type from String for your vertices
01:34 shesek joined
01:34 eacameron joined
01:37 twomix joined
01:37 faberbrain joined
01:38 dsantiago joined
01:41 <Sornaensis> HAPPY PI DAY
01:41 diegoksp joined
01:43 <hsk3> Sornaensis :)
01:43 halogenandtoast joined
01:45 tromp joined
01:46 pie_ joined
01:46 <okeuday_bak> have you used your round function today?
01:47 dee joined
01:48 marcopullo joined
01:49 subttle joined
01:50 vektorweg1 joined
01:52 FreeBirdLjj joined
01:54 danthemyth joined
01:56 takle joined
01:56 mizu_no_oto joined
01:57 dbmikus joined
01:57 <halogenandtoast> Morning all
01:57 nshepper1 joined
02:03 louispan joined
02:03 ubsan_ joined
02:04 wei2912 joined
02:06 benjic joined
02:11 andyhuzhill joined
02:13 zcourts_ joined
02:13 robertkennedy joined
02:15 ali_bush joined
02:15 ali_bush joined
02:17 infinity0_ joined
02:17 infinity0_ joined
02:17 robkennedy joined
02:18 robertkennedy joined
02:19 faberbrain joined
02:19 infinity0 joined
02:20 brixen joined
02:21 benl23 joined
02:21 desktop joined
02:21 cheater joined
02:21 jalnanco joined
02:22 <jalnanco> Hi :)
02:22 infinity0 joined
02:22 ystael joined
02:22 Sergio965 joined
02:23 coltfred joined
02:23 steeze joined
02:23 nomotif joined
02:24 ali_bush joined
02:24 ali_bush joined
02:24 Argue_ joined
02:24 uglyfigurine joined
02:24 louispan joined
02:25 andyhuzhill joined
02:25 Koterpillar joined
02:25 infinity0 joined
02:27 darjeeling_ joined
02:27 sword865 joined
02:28 infinity0 joined
02:28 asmyers joined
02:28 minn joined
02:30 skeet70 joined
02:30 infinity0 joined
02:31 juhp joined
02:32 j2j joined
02:33 Koterpillar joined
02:34 hexagoxel joined
02:34 sanett joined
02:38 sobaken joined
02:38 juhp joined
02:39 xplat joined
02:40 doomlord joined
02:40 louispan joined
02:42 uncertainty joined
02:42 raycoll joined
02:42 wtetzner joined
02:43 michaelw joined
02:43 xaviergmail_ joined
02:44 benjic joined
02:44 sanett joined
02:48 meiji11 joined
02:49 Ninja3047 joined
02:49 robkennedy joined
02:50 DigitalKiwi joined
02:51 takle joined
02:51 buttons840 joined
02:52 eklavya joined
02:53 idupree joined
02:53 bitemyapp joined
02:53 qmm joined
02:54 louispan joined
02:56 idupree joined
02:58 shafox joined
03:00 tromp joined
03:00 ubsan_ joined
03:00 hucksy_ joined
03:00 faberbrain joined
03:02 idupree2 joined
03:03 oisdk joined
03:04 takle joined
03:06 andyhuzhill joined
03:07 robertkennedy joined
03:08 brynedwa1ds joined
03:10 raycoll joined
03:12 Welkin joined
03:12 NextHendrix left
03:13 sobaken joined
03:15 pavonia joined
03:17 andyhuzhill joined
03:19 xall joined
03:20 xtreak joined
03:22 unenforcer joined
03:22 watabou_ joined
03:23 eklavya joined
03:23 ystael joined
03:23 subttle joined
03:24 eacameron joined
03:26 blackdog joined
03:27 mizu_no_oto joined
03:30 the|auriscope joined
03:32 subttle joined
03:37 rkazak_ joined
03:39 juhp joined
03:41 faberbrain joined
03:42 fabianhu joined
03:46 justanotheruser joined
03:48 exferenceBot joined
03:49 chris-medlin joined
03:53 hexagoxel joined
03:53 Koterpillar joined
03:54 melted_ joined
03:59 mac10688 joined
04:01 jsgrant- left
04:01 nak joined
04:02 <nak> can someone explain EitherT to me quick ?
04:02 <nak> specifically, what is: runEitherT :: m (Either e a)
04:02 <nak> m is the monad type we're transforming, right? but what is e and a?
04:02 <Koterpillar> nak: that's not the full type
04:03 <Koterpillar> :t runEitherT
04:03 <lambdabot> error:
04:03 <lambdabot> • Variable not in scope: runEitherT
04:03 <lambdabot> • Perhaps you meant ‘runWriterT’ (imported from Control.Monad.Writer)
04:03 <Koterpillar> :t runWriterT
04:03 <lambdabot> WriterT w m a -> m (a, w)
04:03 <geekosaur> EitherT and MaybeT work a bit differently from the other transformers, iirc
04:03 takle joined
04:03 louisriesener joined
04:03 <Xnuk> @hoogle runEitherT
04:03 <lambdabot> Control.Monad.Trans.Either runEitherT :: EitherT e m a -> m (Either e a)
04:03 <nak> ok so what is "e" and "a" there ?
04:03 <Koterpillar> e is the error type
04:04 <Koterpillar> a is the result
04:04 <geekosaur> but for Either it has two type parameters but a monad can have only one, so the "e" has to be fixed like the "s" in StateT s m a
04:04 <geekosaur> and as usual, "a" is the result type of a computation in the monad
04:04 jsgrant- joined
04:05 <nak> ok so let's pretend we have a Just x or a Nothing
04:05 <nak> how would we use EitherT to transform it ?
04:05 <geekosaur> those are Maybe, not Either, so EitherT isn't the right mapping
04:05 <geekosaur> MaybeT also exists though
04:06 <nak> oh, so EitherT transforms Either TO something else
04:06 <nak> not something TO either
04:06 <nak> mmm that makes more sense
04:06 <geekosaur> depends on how you think of it
04:06 <nak> Ok so let's say we have a Left x or a Right y
04:07 <nak> can we go EitherT to Maybe?
04:07 <geekosaur> e is your x, a is your y
04:07 <geekosaur> EitherT goes to Either, not to Maybe
04:07 <nak> EitherT goes to Either...
04:07 <geekosaur> there is nothing that magically transforms a Maybe to an Either, because you'd have to specify what to map Nothing to
04:07 <pavonia> :t either (const Nothing) Just
04:07 <lambdabot> Either b a -> Maybe a
04:08 <geekosaur> likewise if you wanted to convert an Either (or EotherT) to a Maybe, you;d have to specify what to do about the e
04:08 <geekosaur> (which is to say, the value of a Left)
04:08 <nak> ok so EitherT goes TO an Either tho?
04:08 <nak> from some other type
04:08 <geekosaur> I phrased that badly, I guess
04:09 cschneid_ joined
04:09 <geekosaur> EitherT gives you a way to work with an m (Either e a) without having to dig around inside the m all the time, basically
04:09 <geekosaur> in this sense it's "backwards" from other transformers which put something "on top of" the m
04:10 <nak> mm
04:10 spatial joined
04:10 <pavonia> It's an 'm' enhanced by the opportunity to fail prematurely with an error result
04:11 <spatial> valueofnewstate <- readthevalue a (ReinforcementLearning.index newstate) How do I catch exception and print the values involved ?
04:11 <nak> ok so let's say we do have a Just(Left(x)) or a Just(Right(x))
04:11 <nak> would EitherT help here
04:11 <spatial> Any way to isolate printing in a separate function.
04:12 <nak> ie, iff we were to be okay with demoting the Left(x) down to a Nothing
04:13 tripped joined
04:13 <nak> geekosaur: i guess i'm most confused that e and a are specified when i only have one value at a time
04:14 <geekosaur> you may have only one value, but you have both *types*. one is phantom at any given time
04:14 <geekosaur> if you have a Right 5 :: Either String Int, you cannot use it as an Either Int Int
04:14 <geekosaur> it is still Either String Int
04:17 <spatial> Left and Right. How are they used in valueofnewstate <- readthevalue a (ReinforcementLearning.index newstate) ?
04:20 <geekosaur> spatial, the Left/Right discussion is not related to your question
04:20 mtae joined
04:20 Xanather joined
04:20 <geekosaur> unless the types specify that it is... but I see no types here and have no way to answer as a result
04:21 revtintin joined
04:21 <geekosaur> if there is an actual exception then there is Control.Exception.catch... but I'd want to check the API to see if there's a better way, because exceptions are a lousy way to handle that
04:21 faberbrain joined
04:21 vaibhavsagar joined
04:22 andyhuzhill joined
04:24 ystael joined
04:24 zxiiro_ joined
04:25 ramzifu joined
04:26 <spatial> valueofnewstate <- catch (readthevalue a (ReinforcementLearning.index newstate)(\(SomeException e) -> print $ e) Is this right ?
04:26 <spatial> I am returning some values in a long function though. Just wanted to print at this time.
04:29 andyhuzhill joined
04:31 louispan joined
04:31 <geekosaur> in theory yes, in practice this may bite you unless you can ensure it gets evaluated
04:31 <geekosaur> I did not say "lousy way to handle that" because that's not the Haskell way
04:32 <geekosaur> I said it because *it does not work well with laziness" --- yet it seems like exceptions are the first thing some programmers reach for
04:32 pleax joined
04:32 <geekosaur> some strict language taught them that was the only correct way to think, so they do it in Haskell and then wonder why the exception gets thrown outside the catch
04:33 hexagoxel joined
04:34 skeuomorf joined
04:36 boccato joined
04:37 <spatial> http://lpaste.net/353552 Here attempted to add catch.
04:38 mstruebing joined
04:38 MasseR joined
04:39 <spatial> Looks like I need to return something. But I am just debugging. IO Double and IO ()
04:40 otto_s joined
04:40 suls joined
04:42 <geekosaur> you must return something
04:42 <geekosaur> you are assigning (<-)
04:42 <geekosaur> you must return something that can be assigned
04:44 <spatial> But returning something makes by flow go wrong.Can I return the same value ?
04:44 <geekosaur> what same value?
04:44 <geekosaur> you didnt get a value, you got an exception
04:44 <halogenandtoast> geekosaur: I think this is where you explaination of errors really shines
04:45 <halogenandtoast> s/errors/exceptions/
04:45 <geekosaur> this still hasn't reached the real problem which is that the call that can raise the exception is still lazy and could happen when the result is used, which will be outside the catch so the exception gets thrown
04:46 <geekosaur> IO is not the strict subset of Haskell, it's still lazy
04:46 raycoll_ joined
04:46 <geekosaur> and people get bitten by exceptions happening lazily all the time
04:46 Stavr joined
04:46 Jeanne-Kamikaze joined
04:47 howdoi joined
04:47 <Cale> Er, it's hard to say that execution of IO actions is lazy or eager, because they're not really expressions in a usual way. They describe things which ought to occur in a particular order. If you throw exceptions from the execution of IO actions, they'll be reasonably easy and sensible to catch
04:47 <halogenandtoast> geekosaur: is the solution here to use valueofnewstate somewhere pending the exception returns something?
04:47 <geekosaur> usually, yes. or at least force it somehow
04:47 <Cale> It's just when you're throwing exceptions using throw or error or undefined, from the evaluation of expressions, that things get tricky.
04:48 <Cale> You generally should avoid throwing exceptions from expression evaluation if you have any intention that they be caught.
04:48 <Cale> If you're going to use exceptions, use throwIO
04:50 <Cale> The one *ahem* exception to that is perhaps if you're using a poorly designed library, you may want to catch exceptions that it throws from evaluation for some reason. However, I've forked libraries before rather than do that.
04:51 <Cale> It's less trouble.
04:52 tommd joined
04:52 <halogenandtoast> Cale: speaking of catching exceptions, do you have any insight on this line: https://github.com/halogenandtoast/nhk-reader-haskell/blob/master/Util/Nhk.hs#L79 is there something better I could be doing there?
04:53 hexagoxel joined
04:56 karce joined
04:56 subttle joined
04:56 codesoup joined
05:00 xplat joined
05:02 structuralist joined
05:03 _sras_ joined
05:03 faberbrain joined
05:04 mbuf joined
05:06 xaviergmail_ joined
05:07 andyhuzhill joined
05:08 Swizec joined
05:08 <halogenandtoast> I guess that wasn't only directed at Cale, but they seemed to have strong opinions.
05:08 <Cale> halogenandtoast: Oh, sorry, meant to reply, but got distracted. That looks reasonably sensible to me.
05:09 <halogenandtoast> Cale: No worries, not like I'm paying you for your opinion. Thanks!
05:09 <halogenandtoast> I hate having to typecast it, but I don't use the error
05:09 <halogenandtoast> I guess I could have a function that "eats" the error
05:09 <Cale> You could replace the try with catch
05:09 <Cale> or handle
05:10 <Cale> handle (\(e :: HttpException) -> return Nothing) $ do ...
05:12 <Cale> (and then write the same do-block, only just assume the simpleHttp will work out)
05:12 <halogenandtoast> Does doing it that way provide any benefits (e.g. it's easier to change in the future, etc.)
05:12 <Cale> I dunno, it's about the same
05:12 <halogenandtoast> I haven't used `catch` or `handle` yet
05:12 <halogenandtoast> I didn't even want to use the `try` but simpleHTTP forced me to...
05:12 uncertainty joined
05:13 <halogenandtoast> Actually... annoyingly enough it didn't force me to
05:13 <halogenandtoast> my app failing at runtime forced me to
05:13 <halogenandtoast> boo hiss
05:13 <Cale> Well, yeah, I'm not really a fan of that.
05:14 <halogenandtoast> Rightfully so. I wish it just returned an Either to begin with.
05:14 <Cale> It's reasonably expected that you're going to actually get those exceptions and want to handle them pretty quickly. Just having the result be an Either to begin with would likely be nicer.
05:14 <halogenandtoast> Agreed! We can be friends!
05:15 <halogenandtoast> I feel like well written Haskell code forces me to handle all the cases.
05:15 JoshS joined
05:16 <halogenandtoast> Being surprised with a runtime error is not my cup of tea.
05:17 doubling_ joined
05:17 <halogenandtoast> And of course for me that error was particularly annoying because it only happened on "production" because Akamai had flagged the IP I'm using preventing it from accessing images (using a droplet so I assume someone once used it for something bad).
05:19 steeze joined
05:21 <spatial> catch ( valueofnewstate <- readthevalue a (ReinforcementLearning.index newstate) )(\(SomeException e) -> print e >> return Nothing) Is this the pattern ?
05:21 MasseR joined
05:22 <halogenandtoast> spatial: I assume it could be if readthevalue returns a Maybe
05:23 <halogenandtoast> actually... the catch needs to be to the right of the arrow no?
05:23 <spatial> IO Double. Don't know how I can return a dummy value. Isn't it wrong to do that ?
05:23 Cale joined
05:24 <halogenandtoast> spatial: I think you first have to answer the question, what should happen if readthevalue fails.
05:24 <spatial> I catch and rethrow the exception generally in Java.Or use wrapped exceptions.
05:25 <spatial> Fails.
05:25 ystael joined
05:26 <halogenandtoast> maybe this: valueofnewstate <- catch (readthevalue a (ReinforcementLearning.index newstate)) (\(SomeException e) -> print e >> fail e)
05:26 chu joined
05:27 <spatial> halogenandtoast: Seems like it.
05:28 <halogenandtoast> you might want to use `failIO` there instead
05:28 <halogenandtoast> but I don't know
05:28 systadmin joined
05:28 <halogenandtoast> For Monad IO fail s = failIO s
05:29 <halogenandtoast> So I suppose there is no difference here.
05:29 xtreak joined
05:30 codesoup joined
05:30 <spatial> fail e throws Couldn't match expected type `String' with actual type `e'
05:30 <Cale> Use throwIO
05:31 nomotif joined
05:31 <halogenandtoast> that sounds better
05:33 pleax joined
05:33 connrs joined
05:33 <halogenandtoast> spatial: The issue with fail that I "failed" on was that it expects a string (which you could, but shouldn't in this case, get with show). It also doesn't do what you wanted since it will terminate the program there instead of "reraising" as you put it.
05:33 <Cale> (and pretend that fail doesn't exist)
05:34 xtreak joined
05:34 <halogenandtoast> spatial: Cale is correct in that `throwIO e` should reraise and expects an Exception instead of a string.
05:35 gabe4k joined
05:35 <halogenandtoast> which is more in line with what you wanted. In my perfect world though readthevalue would just return a `IO (Maybe Double)`
05:35 <MarcelineVQ> as someone motly innocent about exceptions, what is being done here? why is catching being done if one isn't doing anything about the caught error? the exception would be printed if left to propogate yes?
05:36 <halogenandtoast> or an `IO (Either Exception Double)` if you really cared about the Exception.
05:36 <spatial> fail is used in unit test to fail and pass the exception test
05:37 <Cale> MarcelineVQ: Sometimes if something external is catching exceptions and keeping quiet about it, something like that would be necessary
05:37 <Cale> But I agree -- usually that shouldn't be needed if you're just going to rethrow
05:40 centril joined
05:42 Rodya_ joined
05:42 <MarcelineVQ> Cale: I see. there's always some potential for something that can get in the way I guess :>
05:42 <spatial> I am just trying to print details at the exception site.
05:42 pwnz0r joined
05:43 marcopullo joined
05:43 osa1 joined
05:45 kritzcreek_ joined
05:45 <Cale> spatial: Don't you already get details though? Is something eating the exception?
05:46 <spatial> readthevalue a (ReinforcementLearning.index newstate) The detail newstate
05:46 vlatkoB joined
05:46 faberbrain joined
05:46 <Cale> ah, so you're printing more than just the exception
05:46 <Cale> fair enough
05:46 unenforcer left
05:48 ajaXHorseman joined
05:49 systadmin joined
05:51 <spatial> Used to stack trace. Does Haskell work like that ?
05:51 uuplusu joined
05:52 MasseR joined
05:52 <geekosaur> not easily, graph reductions are not calls
05:53 <Cale> Well, there are some "CallStack" things now which can be used to give you some idea of where things are taking place. The stack used by GHC isn't a call stack though, so it usually wouldn't be quite as useful at working out what was going on (I think it would be nice to have support for visualising the *actual* stack when something goes wrong too though.)
05:54 <Cale> You'd have to display bits of case expressions or other pattern matches that were waiting.
05:59 Wizek joined
06:01 takle joined
06:07 xtreak joined
06:07 dec0n joined
06:08 hexagoxel joined
06:09 plutoniix joined
06:10 plutoniix joined
06:12 uuplusu joined
06:13 cyborg-one joined
06:15 andyhuzhill joined
06:16 louispan joined
06:17 dni joined
06:18 uuplusu_ joined
06:20 t0by joined
06:20 Prutheus joined
06:24 boccato joined
06:26 ystael joined
06:26 faberbrain joined
06:26 doomlord joined
06:26 tromp joined
06:29 takle joined
06:30 dan_f joined
06:30 edsko joined
06:31 raichoo joined
06:31 <halogenandtoast> spatial: btw, that case on Bool, is there a reason you didn't use if?
06:32 structuralist joined
06:33 <halogenandtoast> if result then ... else ...
06:33 infinity0 joined
06:34 pleax joined
06:35 <spatial> case seems to be more structured in this case because there are other if loops inside In fact if in this case should be replaced with 'when' and 'unless'
06:35 pdgwien joined
06:35 MasseR joined
06:35 <spatial> Because I convert Lisp to Haskell. Lisp used 'when'
06:36 <cocreature> sorry for being pedantic but please don’t call if clauses if loops, there is nothing loopy about them :)
06:37 magthe joined
06:37 <halogenandtoast> spatial: Haskell has those.
06:37 <halogenandtoast> I believe in Control.Monad
06:38 <spatial> Yes
06:38 <halogenandtoast> I'm fine with nested if clauses though.
06:38 <halogenandtoast> but that's me.
06:39 <halogenandtoast> by fine with, what I really mean is that I would eventually extract the into another function
06:39 <halogenandtoast> small functions all day every day.
06:39 <cocreature> halogenandtoast++
06:41 a3Dman joined
06:41 hexagoxel joined
06:44 mkoenig joined
06:44 caumeslasal joined
06:45 pdgwien- joined
06:48 ThomasLocke joined
06:51 systadmin joined
06:52 takle_ joined
06:56 Goplat joined
06:57 connrs joined
06:57 henriksod joined
06:57 andyhuzhill joined
06:58 Sampuka joined
07:00 hdeshev joined
07:01 schell joined
07:04 louispan joined
07:04 Scip joined
07:05 Scip joined
07:07 faberbrain joined
07:08 vlatkoB_ joined
07:10 systadmin joined
07:10 <spatial> randommove :: BoardState -> IO Int How do I print inside If the signature is this ?
07:11 _sg joined
07:11 <srhb> spatial: I'm thinking you're working in a do block. Just be aware that it cannot be the final action (because its type is IO (), not IO Int) - but other than that, you can just putStrLn "whatever"
07:12 a3Dman joined
07:12 s3mi0 joined
07:12 Ayey_ joined
07:12 <spatial> let possibles = possiblemoves state in case possibles of p -> fmap (p !! ) $ randomRIO(0, length p - 1)
07:12 x3kl1 joined
07:12 <srhb> spatial: That is, this is perfectly valid: randommove bs = do { putStrLn "foo"; return 42 }
07:13 Cxom joined
07:14 connrs joined
07:14 mac10688 joined
07:15 <mac10688> I'm looking at reactive-banana examples
07:15 <mac10688> https://github.com/HeinrichApfelmus/reactive-banana/blob/master/reactive-banana/doc/examples/SlotMachine.hs
07:16 <mac10688> on line 107-109 there are functions or variables referenced
07:16 <mac10688> I'm not sure which
07:16 <mac10688> addCredit, removeCredit, addWin that I can't find in scope
07:16 <mac10688> they are defined in a let clause later in the function
07:17 <mac10688> is that the ones I'm seeing because that looks like it's out of scope
07:17 <MarcelineVQ> the key is that the first line is mdo
07:17 <MarcelineVQ> https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#the-recursive-do-notation
07:17 <mac10688> yeah i just saw that for the first time. it's a recursive loop or something?
07:17 <MarcelineVQ> it's something quite interesting I've not learned about yet beyond recognising it
07:18 <mac10688> thanks MarcelineVQ
07:18 louispan joined
07:18 <mac10688> that's good enough. It's bed time. I'll sleep on that
07:21 <spatial> I mean in this p -> fmap (p !! ) $ randomRIO(0, length p - 1)
07:23 uncertainty joined
07:23 eacameron joined
07:25 takuan joined
07:25 <halogenandtoast> spatial: what do you want to print?
07:26 ystael joined
07:27 zeroed joined
07:28 <spatial> Result of fmap (p !! )
07:29 d3wn joined
07:29 Sose joined
07:29 <halogenandtoast> maybe something like: p -> do; res <- fmap (p !!) $ randomRIO(0, length p - 1); print res; res
07:29 ninjazoete joined
07:29 <halogenandtoast> last thing should be return res
07:30 plutoniix joined
07:30 eacameron joined
07:30 patbecich joined
07:31 plutoniix joined
07:31 laz joined
07:32 andyhuzhill joined
07:33 alfredo joined
07:33 xall joined
07:34 <spatial> p -> debug $ fmap (p !! ) $ randomRIO(0, length p - 1) I had to do this
07:34 bjz joined
07:34 <spatial> Something like Aspect Programming for Haskell to weave code instead of that ?
07:34 pleax joined
07:36 LeoVictor joined
07:37 raichoo joined
07:40 raichoo joined
07:40 patbecich joined
07:42 biglama joined
07:42 dc0de joined
07:43 ljc joined
07:43 eacameron joined
07:44 slomo joined
07:45 schell joined
07:46 structuralist joined
07:48 amiri joined
07:48 faberbrain joined
07:48 xmonader joined
07:48 eacameron joined
07:48 sidei joined
07:50 sw1nn joined
07:50 guiben joined
07:51 tfc joined
07:52 <halogenandtoast> Where does debug come from?
07:52 xaviergmail_ joined
07:53 <spatial> Simple function to print and return
07:53 <halogenandtoast> ah so you wrote it.
07:56 fetter_oml joined
07:56 hexagoxel joined
07:57 Koterpillar joined
07:57 thc202 joined
07:58 xtreak joined
08:01 merijn joined
08:02 ragepandemic joined
08:02 eacameron joined
08:04 Iskarlar joined
08:07 dunx_ joined
08:07 oish joined
08:09 raichoo joined
08:10 castlelore joined
08:10 castlelore joined
08:10 thibaud_ joined
08:10 ljc joined
08:12 Beetny joined
08:13 systadmin joined
08:13 dunx joined
08:14 <merijn> ls
08:16 caumeslasal joined
08:19 <u-ou> ls
08:20 V3 joined
08:21 mattyw joined
08:22 <dyreshark> sudo -s
08:22 mero joined
08:23 fendor joined
08:25 Kreest__ joined
08:25 boccato joined
08:26 takle joined
08:26 jessicah joined
08:27 ystael joined
08:29 Miroboru joined
08:30 faberbrain joined
08:30 louispan joined
08:31 caumeslasal joined
08:32 zero_byte joined
08:32 revtintin joined
08:33 systadmin joined
08:33 caumeslasal1 joined
08:35 albertid joined
08:35 connrs joined
08:35 pleax joined
08:36 doomlord joined
08:38 _sras_ joined
08:39 <_sras_> Is there any issues with using WriterT for logging for a web application?
08:39 aib joined
08:41 cur8or joined
08:41 patbecich joined
08:44 yogsototh joined
08:44 cyphase joined
08:45 <jle`> WriterT isn't really meant for streaming logging
08:46 Argue__ joined
08:46 pwnz0r joined
08:46 <jle`> you should probably use a proper logging type instead
08:47 <jle`> streaming logging is just not something that WriterT's purpose is even remotely related to
08:47 razi1 joined
08:47 TheEpsylon joined
08:48 mtae left
08:49 shurick joined
08:55 bjz_ joined
08:57 halogenandtoast joined
08:58 kosorith joined
08:59 Mehdi2277 joined
09:00 ramzifu joined
09:05 jshjsh joined
09:07 tomphp joined
09:09 OnkelTem joined
09:10 eacameron joined
09:10 <dmj`> _sras_: I wouldn’t keep a WriterT around throughout the life of the web application. On each request a thread is forked that evaluates your monad stack completely. The monoid you accumulate from WriterT could be used to write to some kind of logging framework, either to disk or external api
09:11 faberbrain joined
09:14 balor joined
09:17 louispan joined
09:17 j201[m] left
09:17 jacobm[m] left
09:17 sazert[m] left
09:17 yerhausin[m] left
09:17 shiona[m] left
09:17 ayk[m] left
09:17 TesX[m] left
09:17 jmnoz[m] left
09:17 rodoa96[m] left
09:17 M-wamaral left
09:17 bolton left
09:17 M-Shrike left
09:17 el_tejon[m] left
09:17 SteinsGate[m] left
09:17 isair[m] left
09:17 na9da[m] left
09:17 fotonzade joined
09:18 ccomb joined
09:18 <spatial> nextstate :: Player -> BoardState -> Int -> BoardState IO and non-IO are still confusing. Is there a way to print in that function ?
09:18 andyhuzhill joined
09:19 uglyfigurine joined
09:20 <spatial> Otherwise I have to debug wherever that function is called.
09:20 niez joined
09:20 <Mehdi2277> If I wanted to go about creating an iOS application with swift as the front end and haskell for the logic how should it be done? I've been trying to set up ghc-ios, but have been having trouble.
09:21 <_sras_> jle`: I am using Servant web framework. In the example in the Servants manual, the logger only logs the current request. How can I log a custom message from a route handler?
09:21 Kreest_ joined
09:22 <bartavelle> _sras_, you can use one of the logging libraries, or just 'putStrLn' stuff
09:24 <_sras_> bartavelle: Logging libraries for servant?
09:24 <bartavelle> you don't have to use something that's servant related, you are if i'm not mistaken in "ExceptT ServantErr IO"
09:24 <bartavelle> so you can liftIO anything that's IO
09:25 <bartavelle> gimme a sec
09:25 rgc_ joined
09:25 <bartavelle> that was for an old servant version : http://hbtvl.banquise.net/posts/2015-06-28-servantintegration.html
09:26 <bartavelle> but you can see that I can run "SqlPersistT (LoggingT (EitherT ServantErr IO)) a" in the handlers
09:26 <bartavelle> for this instance, you can just wrap your logic into the LoggingT transformer and you're done
09:27 tromp joined
09:27 <dmj`> _sras_: there are functions to help you log from Writers, that was the intention of the logWriterT*Nat family of functions
09:28 <dmj`> w/ servant, in servant-server
09:28 <dmj`> logWriterTLNat :: MonadIO m => (w -> IO ()) -> (:~>) * (WriterT w m) m
09:28 ystael joined
09:28 <bartavelle> oh wow
09:28 <dmj`> so you can keep a WriterT in your stack, and inside the natural transformation, unwrap it to Handler a, but log while doing so
09:28 <dmj`> bartavelle: yea, the lesser known parts of servant :)
09:29 Thra11 joined
09:29 thunderrd joined
09:30 <_sras_> dmj`: I am using a custom monad and use the"Nat" stuff to work with the servants Monad. Is this what you are trying to say?
09:30 pleax joined
09:30 <bartavelle> apparently with any monad
09:30 <bartavelle> that's MonadIO
09:31 magicman joined
09:32 <dmj`> _sras_: yea, if you add WriterT to your stack (might also want to derive MonadWriter YourMonoidGoesHere) then in the Nat function, you’d use logWriterTLNat when you hit the WriterT of wrapping, and supply some (w -> IO ())
09:32 revtintin joined
09:32 BartAdv joined
09:33 andyhuzhill joined
09:33 <dredozubov> is it possible to supply a heap volume threshold to RTS after which the GC sweep comes in?
09:33 <dredozubov> i have to use -H to do that, but it seems like it can lead to heap bloating in some cases
09:34 meandi joined
09:35 tomphp joined
09:36 aib joined
09:36 Rizy joined
09:38 plugin joined
09:43 farao joined
09:43 <_sras_> dmj`: http://lpaste.net/7590969248134987776 this is my current setup. I just throw away the writer's log.
09:43 farao joined
09:43 plutoniix joined
09:44 plutoniix joined
09:44 subttle joined
09:45 xtreak joined
09:46 silver joined
09:46 oish joined
09:48 marr joined
09:48 takle_ joined
09:51 merijn joined
09:51 gregman_ joined
09:52 Iskarlar joined
09:52 Thra11 joined
09:53 faberbrain joined
09:54 osa1 joined
09:54 osa1 joined
09:55 FullyFunctional joined
09:56 ub joined
09:56 pleax joined
09:57 phaji joined
09:57 kpglvm joined
09:59 FreeBirdLjj joined
10:01 bjz joined
10:01 ramzifu joined
10:02 <ph88^> how can i make this little piece of code more clean? https://bpaste.net/show/1a35034bc254
10:06 mmn80 joined
10:06 <ongy> ph88^: I think 2 matches would look a bit cleaner, so first match on the input then get the output action (or the other way around)
10:06 <ph88^> ongy, not sure what you mean with 2 matches
10:08 louispan joined
10:09 jaspervdj joined
10:10 fendor joined
10:11 <lpaste_> ongy pasted “for ph88” at http://lpaste.net/353554
10:11 <ongy> something like that
10:11 <ongy> not sure if I did it all correctly, but I think it shows what I mean
10:12 <ph88^> ooh right
10:13 <ph88^> thanks ongy
10:13 <ph88^> another question, i was searching for a function with signature Char -> Word8 but i couldn't find it on hoogle, anyone knows ?
10:14 <Rembane> ph88^: Are you working with Bytestrings?
10:14 <liste> ph88^: what should it do with chars over 255 ?
10:14 <ph88^> yes i work with bytestrings
10:15 nilof joined
10:15 <ph88^> only chars that can be represented in a single byte are valid
10:15 <ph88^> actually this gives me an idea .. i am using optparse-applicative .. so maybe i should just specify Word8 in the first place
10:15 <Rembane> ph88^: Use the variant of the ByteString library that works best for you.
10:16 <Rembane> ph88^: This one for instance: https://hackage.haskell.org/package/bytestring-0.10.8.1/docs/Data-ByteString-Char8.html
10:17 mattyw joined
10:17 <ph88^> Rembane, there is no Char -> Word8 function there
10:17 <ph88^> i have this piece of code padding = lazyByteString $ B.take (size - B.length rest) $ B.repeat padByte
10:18 systadmin joined
10:18 <ph88^> padByte type is wrong at the moment
10:18 <ph88^> i'm trying to make a bytestring builder
10:19 <Rembane> ph88^: You don't need the Char -> Word8 function if you use Data.ByteString.Char8 instead of Data.ByteString.
10:19 revtintin joined
10:20 <ph88^> is that compatible with the builder ?
10:20 rgr joined
10:20 <Rembane> ph88^: Your builder?
10:21 <ph88^> Module ‘Data.ByteString.Char8’ does not export ‘repeat’
10:21 <ph88^> :/
10:22 Thra11 joined
10:22 <Rembane> ph88^: Which Bytestring module exports repeat? I can't find it.
10:22 <ph88^> Rembane, i mean with the builder lazyByteString :: ByteString -> Builder
10:23 <ph88^> Rembane, https://hackage.haskell.org/package/bytestring-0.10.8.1/docs/Data-ByteString-Lazy.html#v:repeat
10:23 <Rembane> ph88^: https://hackage.haskell.org/package/bytestring-0.10.8.1/docs/Data-ByteString-Lazy-Char8.html#v:repeat
10:23 <Rembane> ph88^: The lazy bytestring equivalent of what I said. :)
10:24 Iskarlar joined
10:25 <ph88^> it type check now, thaks Rembane
10:26 albel727 joined
10:26 balor joined
10:26 whiteline joined
10:26 <Rembane> ph88^: No worries. The ByteString modules are a jungle. :)
10:27 boccato joined
10:29 <ph88^> ongy, from your idea i made this https://bpaste.net/show/8488bd735c4a
10:29 ystael joined
10:30 yaesposi joined
10:30 rcat joined
10:32 hexagoxel joined
10:33 Vorpal joined
10:33 Vorpal joined
10:33 Guest9965 joined
10:35 Guest9965 joined
10:35 faberbrain joined
10:35 eacameron joined
10:36 revtintin joined
10:37 sidei joined
10:38 marfoldi joined
10:40 tommd joined
10:40 xaviergmail_ joined
10:42 Iskarlar joined
10:42 pleax joined
10:44 IndigoTiger_ joined
10:45 mofasa_ joined
10:46 shafox joined
10:47 jshjsh joined
10:48 Axman6 joined
10:48 Iskarlar joined
10:50 exferenceBot joined
10:50 dhil joined
10:52 Thra11 joined
10:53 geekosaur joined
10:53 cfricke joined
10:53 fizruk joined
10:54 pleax joined
10:56 dhananjay joined
10:56 Gurkenglas joined
10:56 blueonyx joined
10:57 Iskarlar joined
11:02 Snircle joined
11:04 JuanDaugherty joined
11:04 eklavya_ joined
11:04 Jackneill joined
11:06 sidei joined
11:07 blueonyx_ joined
11:08 yellowj joined
11:11 UserJosh joined
11:12 Levex joined
11:13 spatial joined
11:13 <spatial> Trying to print and it isn't possible . http://lpaste.net/353557
11:14 <spatial> IO doesn't mix
11:14 <spatial> What is the usual way ?
11:16 Thra11 joined
11:16 faberbrain joined
11:17 tsmish joined
11:17 coot joined
11:19 Iskarlar joined
11:21 <ongy> spatial: that looks like a type error to me
11:21 <spatial> No
11:21 <ongy> 'mapM_ (putStr . show) xloc' shouldn't expect another argument
11:21 <spatial> Just added mapM to check.
11:22 <ongy> does that exact thing you pasted compile? if so, what would you expect it to do, and what does it do?
11:23 <spatial> mapM doesn't mix with the function. Removed.
11:23 plugin joined
11:24 <spatial> nextstate player (BoardState xloc oloc index) move= BoardState newx newo newindex where
11:25 <spatial> Introduce trace here. How ?
11:25 guampa joined
11:25 unK_ joined
11:25 drunK joined
11:26 <ongy> there's Debug.Trace which exports trace (or if you have a show instance, probably nicer to use traceShowId)
11:27 halogenandtoast joined
11:28 tromp joined
11:28 doomlord joined
11:29 doomlord joined
11:29 <spatial> How does that function change ? Not a Haskell expert yet
11:30 ystael joined
11:30 Johannes13_ joined
11:30 <ongy> nextstate player (BoardState xloc oloc index) move= traceShowId $ BoardState newx newo newindex where -- It should work like this
11:30 doomlord joined
11:30 <ongy> also don't expect it to work exactly as you think, this is sill subject to lazyness
11:31 <spatial> trace "log" $ BoardState newx newo newindex where
11:31 doomlord joined
11:32 <spatial> ongy:It worked with show
11:32 JeanCarloMachado joined
11:33 cur8or joined
11:35 blueonyx joined
11:35 pleax joined
11:37 phaji joined
11:38 asthasr joined
11:39 tomboy64 joined
11:39 blueonyx_ joined
11:39 blueonyx joined
11:40 ramzifu joined
11:41 codesoup joined
11:42 systadmin joined
11:43 xall joined
11:43 chrisdotcode joined
11:47 revtintin joined
11:49 Thra11 joined
11:49 uncertainty joined
11:50 alanb99 joined
11:50 Unhammer joined
11:50 alanb99 left
11:54 armyriad joined
11:55 hdeshev joined
11:55 structuralist joined
11:57 faberbrain joined
11:59 dfeuer joined
12:01 xall joined
12:01 Iskarlar joined
12:01 sdothum joined
12:02 HoierM joined
12:02 mizu_no_oto joined
12:03 cyborg-one joined
12:07 nutzz joined
12:08 uncertainty joined
12:08 Rizy joined
12:09 a3Dman joined
12:10 V3 joined
12:12 <doubling_> hello. Are any haskell maintainers here
12:12 doubling_ left
12:13 netheranthem joined
12:14 sepp2k joined
12:15 blueonyx_ joined
12:15 oish_ joined
12:16 pleax joined
12:16 boombanana joined
12:17 Mortomes|Work joined
12:18 blueonyx_ joined
12:19 sidei joined
12:19 erisco joined
12:19 Thra11 joined
12:20 blueonyx joined
12:23 mizu_no_oto_work joined
12:23 a3Dman joined
12:23 plugin joined
12:24 cpennington joined
12:25 wei2912 joined
12:27 lep-delete joined
12:27 CurryWurst joined
12:29 boccato joined
12:30 lukaramu joined
12:30 ystael joined
12:31 silentcontributo joined
12:32 wjp1 joined
12:33 unK_ joined
12:35 eklavya joined
12:35 ali_bush joined
12:35 ali_bush joined
12:38 jophish_ joined
12:39 bjz joined
12:39 faberbrain joined
12:40 tommd joined
12:40 czeq joined
12:44 tromp joined
12:44 vaibhavsagar joined
12:45 MarioBranco joined
12:45 centril joined
12:46 mmn80 joined
12:46 coltfred joined
12:47 systadmin joined
12:47 mohsen_ joined
12:48 Rizy joined
12:51 fizruk joined
12:52 prkc joined
12:52 tromp joined
12:53 freusque joined
12:55 MarioBranco joined
12:55 yamadapc joined
12:56 crobbins joined
12:59 jhrcek joined
12:59 yellowj joined
13:00 _sras_ joined
13:01 <_sras_> is there a function similar to intercalate that uses monoid instances?
13:02 revtintin joined
13:04 <merijn> :t intercalate
13:04 <lambdabot> [a] -> [[a]] -> [a]
13:05 <merijn> _sras_: Well, what would that do?
13:05 <liste> :t intersperse
13:05 <lambdabot> a -> [a] -> [a]
13:05 cdg joined
13:05 <merijn> I'm not sure how "monoid instances" would related to what intercalate does?
13:05 HoierM_ joined
13:05 <Taneb> I presume Monoid m => m -> [m] -> m
13:06 <liste> @hoogle Monoid m => m -> [m] -> m
13:06 <lambdabot> BasicPrelude intercalate :: Monoid w => w -> [w] -> w
13:06 <lambdabot> Clay.Property intersperse :: Monoid a => a -> [a] -> a
13:06 <lambdabot> Language.PureScript.Docs.Utils.MonoidExtras mintersperse :: (Monoid m) => m -> [m] -> m
13:06 <lyxia> intercalate x [a,b,c] = mconcat [a, x, b, x, c]
13:06 <merijn> Well, isn't that just "mconcat . intersperse"?
13:06 <_sras_> merijn: Got it. intercalate in https://hackage.haskell.org/package/string-combinators-0.6.0.5/docs/Data-String-Combinators.html
13:06 uncertainty joined
13:07 ramzifu joined
13:07 V3 joined
13:07 <merijn> huh
13:07 <merijn> That's a super confusing type
13:08 fuzzy_id joined
13:09 alfredo joined
13:09 mada joined
13:10 <tabaqui1> there are some api functions in signals library
13:10 <tabaqui1> f.e
13:10 Glooomy joined
13:10 <tabaqui1> sigint :: CIint
13:11 <tabaqui1> siging = 2 -- I guess
13:11 <tabaqui1> and I cannot use this symbols in pattern matching
13:11 <merijn> That's not a function
13:11 <merijn> That's just a variable
13:11 dario` left
13:11 <tabaqui1> hm, ok
13:11 <merijn> And no, you can't pattern match identifiers
13:12 <tabaqui1> only with basic data constructors?
13:12 <tabaqui1> no aliases?
13:12 <merijn> There's no notion of aliases in the language
13:13 <tabaqui1> but ghc can extract actual value, stored in sigint
13:14 <tabaqui1> or I cannot see possible issues
13:14 <tabaqui1> or there is no issues
13:14 <merijn> tabaqui1: Well, sigint could be an arbitrary expression, so how would it do that?
13:15 <tabaqui1> merijn: ghc could evaluate pure expression
13:15 <merijn> tabaqui1: That can take arbitrarily long, people already think GHC compilation takes too long
13:15 wei2912 joined
13:15 <tabaqui1> in runtime I mean
13:16 <Tuplanolla> You know guards do that, tabaqui1.
13:16 <merijn> tabaqui1: THen you could just use a guard using ==
13:16 <tabaqui1> yeah, I could but prefer case notation
13:17 riaqn joined
13:17 <tabaqui1> I mean ghc *can* do such things
13:17 <lyxia> pattern SigInt = 2 case signal of SigInt -> ...
13:17 <tabaqui1> and there will be no collisions
13:17 <riaqn> Hello, is graph reduction in haskell optimal? (in levy's sense)
13:17 danthemyth joined
13:17 <merijn> lyxia: That requires modifying the library and isn't compatible with old versions
13:17 Tesseraction joined
13:17 <lyxia> :(
13:18 danthemyth joined
13:18 <tabaqui1> ah, ok
13:18 <tabaqui1> I get it
13:19 <riaqn> say, f x y = (8 + x) * y, and g = f 9, and (g 10) and (g 11) will involve two computations of (8 + 9) I guess?
13:19 <tabaqui1> ghc doesn't know, must he compare it with existing variable, or bind it as a local var
13:19 <tabaqui1> *it compare
13:19 silver joined
13:20 geekosaur joined
13:20 doodlehaus joined
13:20 sphinxo joined
13:20 jomg joined
13:20 <lyxia> riaqn: that depends on the implementation
13:20 faberbrain joined
13:21 Coldblackice joined
13:21 oisdk joined
13:22 eschnett joined
13:22 Khisanth joined
13:23 rgr joined
13:24 silentcontrib joined
13:25 a3Dman joined
13:26 oisdk joined
13:27 pleax joined
13:29 dhil joined
13:29 asmyers joined
13:29 shafox joined
13:30 [JIHADI] joined
13:30 <riaqn> lyxia:sure it does. But what about ghc?
13:31 ystael joined
13:31 V3 joined
13:32 <riaqn> I can imagine that compiler can transform the program to f = \x -> (\s y -> s * y) (8 + x), so this won't be a problem anymore.
13:32 <erisco> I don't know the answer, but I would be concerned if it always did this
13:33 <erisco> addition is cheap, whereas having separate functions for every g x would be pricey
13:33 <riaqn> but I think that couldn't achive the same level of sharing as "optimal reduction"
13:33 <Tuplanolla> The catch is that maximal sharing isn't optimal in practice, riaqn.
13:33 <erisco> if there is no substantial reduction I would not want it to do this
13:34 <riaqn> Tuplanolla: Yeah I read that a lot on internet.
13:34 <Tuplanolla> Here's evidence.
13:34 lukaramu_ joined
13:35 <Tuplanolla> :t Data.Vector.force
13:35 <lambdabot> Data.Vector.Vector a -> Data.Vector.Vector a
13:35 <riaqn> Tuplanolla: some even says that, optimal reduction on fibonacci achieve something similar to memorization.
13:35 <riaqn> which is expensive, and certainly not expected by programmers.
13:35 <Tuplanolla> That function is `id`, but breaks sharing internally.
13:37 <riaqn> OK. so I guess the sharing level of "call by need" is the balance point.
13:37 oisdk joined
13:37 <riaqn> together with weak head normal form.
13:37 <Tuplanolla> As long as we have finite memory...
13:37 rekahsoft joined
13:38 <erisco> and finite bandwidth
13:38 <riaqn> Tuplanolla: so it's common for optimal reduction to use much more memory?
13:38 <riaqn> wow wasn't expecting that.
13:38 <Tuplanolla> I don't know about common, but that's what happens here.
13:38 ChristopherBurg joined
13:39 dbmikus joined
13:40 ccomb joined
13:40 sidei joined
13:40 <riaqn> Tuplanolla: OK, thanks!
13:40 jhrcek joined
13:40 dhananjay left
13:41 [JIHADI] left
13:42 ystael joined
13:43 mizu_no_oto_work joined
13:44 shayan_ joined
13:44 tomphp joined
13:45 uncertainty joined
13:45 Iskarlar joined
13:50 merijn joined
13:51 plutoniix joined
13:51 V3 joined
13:51 <robertkennedy> How can I get ghci to actually store big variables? Ie `let s = takeWhile (< 100000) $ dropWhile (< 90000) primes`
13:51 meba joined
13:51 <robertkennedy> Then if I run length s twice it takes a long time
13:52 xaviergmail_ joined
13:53 <erisco> the second as long as the first?
13:55 <erisco> it does have to count the list twice, and it will have something like 4000 elements, so it will take some time ("long time" isn't a number so I don't know what we're referencing)
13:56 <robertkennedy> Oh no it's clearly regenerating s both times
13:56 Welkin joined
13:57 <robertkennedy> I checked via length [1..10000], which is quick enough.
13:58 <erisco> maybe it is a REPL thing? I don't know
13:58 dsh joined
13:58 stephA joined
13:59 ramzifu joined
13:59 ystael joined
13:59 Lord_of_Life joined
14:00 takle joined
14:00 eacameron joined
14:00 danharaj joined
14:00 <tdammers> let s = primes `seq` takeWhile (< 100000) (dropWhile (< 90000) primes) -- maybe this helps?
14:01 <tdammers> or rather, you probably want to even force `s` in the context where you're taking the length twice
14:01 <tdammers> not sure though
14:01 <tdammers> might wanna profile?
14:02 <erisco> if the REPL works by re-evaluating from the top then this makes sense (and assuming you are using the REPL)
14:03 faberbrain joined
14:03 <merijn> The general rule is: Don't rely on ghci for ANYTHING relating to optimisations and performance
14:03 <erisco> what if you try (length s, length s) ?
14:04 `^_^v joined
14:04 <erisco> there are libs that run like crap in the REPL too, so watch out
14:05 djellemah_ joined
14:05 czeq joined
14:05 mettekou joined
14:07 Rizy joined
14:08 mikecaruso joined
14:08 plugin joined
14:10 <lyxia> robertkennedy: what type do you get for s
14:11 balor joined
14:12 cschneid_ joined
14:12 pleax joined
14:14 mikecaruso joined
14:14 <merijn> lyxia: Oooh! You might be on to something, lack of MMR in ghci
14:15 <erisco> match-making rating?
14:15 <cocreature> monomorphism restriction
14:15 <merijn> erisco: monomorphism restriction
14:16 <merijn> Last time we talked about it people were saying "that never happens and if it did you wouldn't notice it!", but if that's the case here, this might be exhibit A for keeping the MMR always on :)
14:16 <merijn> robertkennedy: How did you define primes?
14:17 mizu_no_oto_work joined
14:17 <erisco> is that suggesting s has a polymorphic type and that is why it evaluates twice?
14:17 steeze joined
14:17 <cocreature> yep
14:17 <merijn> erisco: If primes does too, then yes
14:17 <erisco> gotta stick in the specialize pragma I suppose
14:18 <cocreature> or just specialize manually
14:18 <merijn> erisco: Or just use ghc (which would yell at you due to MMR) or add a type signature
14:18 dan_f joined
14:19 <erisco> that's just funny
14:19 <merijn> erisco: Well, this is the exact reason why the MMR exists in ghc :p
14:19 <erisco> so does (length s, length s) evaluate twice but let t = s in (length t, length t) not?
14:19 <merijn> It's not in ghci since it's usually annoying for interactivity
14:19 <merijn> erisco: The answer is: unspecified
14:20 Levex joined
14:20 <merijn> erisco: GHC has CSE (common subexpression elimination), but whether it fires is...not 100% reliable
14:20 <Welkin> you mean does s evaluate twice? or does `length s` evaluate twice?
14:20 <erisco> s
14:20 <erisco> or t, in the second example
14:20 <merijn> erisco: So, honestly there's no way to know wheter it evaluates 's' twice or even 'ength s' twice
14:20 <merijn> Welkin: Well, GHC is in no way required to evaluate 's' OR 'length s' twice in that example
14:21 <Welkin> I would assume that s is evaluated once
14:21 <Welkin> because it refers to the same expression/value
14:21 <merijn> Welkin: Most people would, which is why we have the MMR :)
14:21 <erisco> but it is polymorphic Welkin
14:22 <merijn> Although Haskell doesn't require anything, of course
14:22 <erisco> so it is different things depending on the chosen type
14:22 <Welkin> you mean like is you have (String, Text)?
14:22 <merijn> Welkin: No, if 's :: Num a => [a]'
14:23 <merijn> Welkin: You can't simply store the evaluation of 's', since it depends on the selected Num instance
14:23 <erisco> you can use the specialise pragma, or manually specialise
14:23 <erisco> or it could specialise based on found uses
14:23 freeside joined
14:23 <erisco> or it could even memoise at runtime
14:23 <erisco> who knows
14:24 <merijn> erisco: Haskell spec doesn't ban using magic to determine the result ;)
14:24 <shapr> Type Driven Development! w00!
14:24 <tdammers> Compiler Error Driven Development!
14:25 <cocreature> stackoverflow driven development!
14:25 <erisco> you mean development
14:25 Bhootrk_ joined
14:26 wraithm joined
14:26 <freeside> https://www.jwz.org/images/supercoder-2000-nur-1-und-0-und-done.jpg
14:26 preyalone joined
14:26 nbro joined
14:26 <Unhammer> why does it have that "done" key, seems superfluous
14:26 <nbro> hi
14:27 <erisco> I should show this to people who think programming must be all 0's and 1's
14:27 <erisco> yes, this is what I type on every day, you're right
14:27 HarveyPwca joined
14:27 <nbro> I’m trying to understand how to fake "loops" in haskell by using an "auxiliary" function
14:27 <merijn> nbro: Usually depends on the kinda loop you're wanting to do
14:28 <nbro> I’m just trying to understand the syntax
14:28 <tdammers> it's not really fake, there's just two layers of abstractions in between
14:28 fendor joined
14:28 <freeside> https://hackage.haskell.org/package/loops-0.2.0.2/docs/Control-Monad-Loop.html
14:28 <nbro> here you have an example of such a thing for the factorial: https://en.wikibooks.org/wiki/Haskell/Recursion
14:28 <nbro> factorial'' n = go n 1
14:28 <nbro> where
14:28 <nbro> go a res
14:28 <nbro> | a > 1 = go (a - 1) (res * a)
14:28 <nbro> | otherwise = res
14:28 <cocreature> @where lpaste
14:28 <lambdabot> http://lpaste.net/
14:28 <cocreature> please paste your code there and send the link here
14:29 <freeside> http://dl.acm.org/citation.cfm?id=968579
14:29 <nbro> http://lpaste.net/353563
14:29 <erisco> understand that that is an exaggerated example. You'd not write factorial like that
14:29 <tdammers> nbro: haskell is a pure language, so loops like we can write them in an imperative language with mutable state updates aren't possible
14:30 <nbro> erisco: I’m just trying to understand the syntax
14:30 <nbro> it doesn’t matter if that’s the best way or not
14:30 <tdammers> nbro: the syntax has nothing to do with loops or recursion
14:30 boccato joined
14:30 <tdammers> nbro: basically all you need to produce a loop is a function that calls itself
14:30 <merijn> tdammers: Well, maybe his question is not about loops or recursion :)
14:30 <nbro> that’s the way authors are describing it
14:30 <erisco> what parts of the syntax do you not understand?
14:30 <freeside> thou base coder, for coding in that style, thou shalt be cursed and cursed again
14:31 <nbro> tdammers: please, I know how to write recursive functions, I’m just trying to understand the syntax above
14:31 <Cale> haha
14:31 <merijn> nbro: What syntax part confuses you?
14:31 <tdammers> nbro: do you mean the | part?
14:31 <erisco> yeah, puh-leez tdammers
14:31 <nbro> merijn: exactly how the control flow would happen
14:32 <tdammers> nbro: there is no control flow, just functions defined in terms of one another
14:32 <Cale> nbro: So a and res start at n and 1 respectively, and then so long as a > 1, we subtract 1 from a, and multiply res by a
14:32 <tdammers> nbro: evaluation order and control flow arise from the call graph
14:32 <Cale> nbro: and then once a is no longer greater than 1, we produce res as the result
14:33 <tdammers> nbro: you can trace the "control flow" by evaluating the function by hand - it's mostly just pattern matching and substitution
14:33 <freeside> res ipsa loquitur, really
14:33 sasinello joined
14:33 <erisco> I don't think we talk about "control flow", we talk about "evaluation order"
14:33 <tdammers> e.g., if you want to evaluate `factorial'' 2`, the first line says you can susbtitue `go 2 1`
14:33 <sasinello> ciaoo
14:33 <sasinello> !list
14:34 sasinello left
14:34 <Cale> Yeah, we can do it algebraically: factorial'' 4 = go 4 1 = go 3 (4*1) = go 2 (3*4*1) = go 1 (2*3*4*1) = 2*3*4*1
14:34 <nbro> Cale: exactly what I wanted to hear...
14:34 <nbro> essentially we call another function inside the function factorial''
14:34 <tdammers> yes
14:34 <nbro> by passing to it the initial parameters
14:34 <nbro> ok
14:35 <Cale> Yeah, it's a little weird to think of this as "calling" since it's outermost-first evaluation and there's no call stack
14:35 <tdammers> you could also just write go as a top-level function in this example
14:35 <Cale> but yes
14:35 <nbro> I’m still not really familiar with wheres and dos
14:36 <nbro> and I still need to understand when can I use them
14:36 cdg joined
14:36 <Cale> Well, do is for gluing together a bunch of actions in some monad to form a larger action.
14:36 <erisco> well, if you want to use foreign jargon, then stuff after "where" is like hoisted local variables
14:36 PennyNeko joined
14:36 revprez joined
14:36 <tdammers> `where` is pretty simple, think of it as introducing a local scope for the definition that it follows
14:36 <Cale> 'where' is for making definitions which scope over the rest of your declaration
14:37 <nbro> Cale: the problem is that I still need to learn about monads… I know IO() is a monad and monads are used apparently when side effects could happen?
14:37 <nbro> honestly I still need to read bout those things
14:37 <tdammers> `do` is syntax sugar for monadic code; best way to "understand" it is to learn the desugaring rules and apply them to a bunch of examples
14:37 <Cale> IO is a monad, and IO is used to describe effects
14:37 <freeside> for completeness please contrast "where" with "let/in"
14:38 fosskers joined
14:38 <Cale> But other monads might have different qualities to them -- what they share is basically a particularly-shaped API which seems to come up often.
14:38 sidei joined
14:38 <erisco> IO is a monad, not IO (), and monads provide an interface to cope with side-effects but that is not the only use of them
14:38 vydd joined
14:38 <Cale> For example, the list type constructor is also a monad, and so we can write things like:
14:38 ph88 joined
14:39 <Cale> > do x <- [1,2,3]; y <- [4,5]; return (x,y)
14:39 <tdammers> s/side-effects/effects/
14:39 <lambdabot> [(1,4),(1,5),(2,4),(2,5),(3,4),(3,5)]
14:39 erctng joined
14:39 <nbro> I know that let … in … is somehow equivalent to … where ...
14:39 <Cale> Yes
14:39 <tdammers> also, it's not that you need monads to model effects
14:39 <nbro> not sure if they are really interchangable everywhere
14:39 <ph88> hi guys, i use stack build on one system and then move the executable to another system (with same OS) and it doesn't work because it says: can not find shared library libgmp.so.10 .. how can i make sure that the binary always works ?
14:39 <Cale> The difference being that 'where' is part of the declaration syntax rather than expression syntax
14:40 <Cale> and will scope over multiple guards
14:40 <Cale> But otherwise, they are equivalent
14:40 <tdammers> just that the "shape" of code that models effects usually forms a monad, and Haskell just decided to make this explicit in the form of the Monad typeclass
14:40 theorb joined
14:41 tommd joined
14:41 HoierM joined
14:41 <nbro> why is the list type constructor a monad?
14:41 afcondon_ joined
14:41 ReinH joined
14:41 ajmccluskey joined
14:41 <Cale> Well, a monad consists of three things:
14:41 <Cale> 1) A type constructor M
14:41 <Cale> 2) A function return :: a -> M a
14:42 <Cale> 3) A function (>>=) :: M a -> (a -> M b) -> M b
14:42 <Cale> (and return and (>>=) have to satisfy some conditions I'll gloss over for now)
14:42 <Cale> For lists, we have
14:42 <Cale> return :: a -> [a]
14:42 <Cale> and
14:42 <Cale> (>>=) :: [a] -> (a -> [b]) -> [b]
14:42 <Cale> Can you come up with functions of those types?
14:42 <Cale> Chances are, the first thing you come up with will be the right ones :)
14:43 skeuomorf joined
14:44 <erisco> oh I don't know about that, there are lots of ways to get it wrong too :P
14:44 <Cale> There are ways to get it wrong for sure
14:44 faberbrain joined
14:44 <Cale> But the right thing is perhaps the most intuitive thing to do
14:45 <nbro> Cale: mm.. honestly I need to read a full article about these topics, I’ve just read a little bit here and there
14:45 <tdammers> return = repeat; (>>=) = const [] -- >:-> ignore me
14:45 <Cale> nbro: The best way to proceed is probably just to look at examples of monads one by one
14:45 <nbro> Cale: ok, thanks again!
14:45 <freeside> to put it all together, a text like haskellbook.com might also be useful
14:45 <nbro> @lpaste
14:45 <lambdabot> Haskell pastebin: http://lpaste.net/
14:45 <nbro> lol
14:46 <eacameron> I'd like to use https://github.com/hvr/multi-ghc-travis or something like it for travis builds, but I have multiple cabal projects in my repo. Does anyone have an example of how to do that?
14:46 <tdammers> nbro: seriously; I recommend ignoring do notation until you understand plain monadic code (using >>= and return)
14:46 <merijn> Yes
14:46 <Cale> tdammers: That'll fail the law that x >>= return = x
14:46 <merijn> I would always recommend beginners to avoid do-notation until you're comfortable with >>=
14:46 <erisco> well you glossed over that Cale :P
14:46 <Cale> tdammers: also return v >>= f = f v ;)
14:46 <Cale> erisco: That's fair :)
14:47 <merijn> I like >>= for implementation, but I dislike it for laws
14:47 <merijn> >=> is so much more elegant
14:47 robkennedy joined
14:48 <erisco> and others like join
14:48 <merijn> Can you specify the laws with join?
14:48 <Cale> merijn: What, you don't like (x >>= f) >>= g = x >>= (\v -> f x >>= g) ;)
14:48 <erisco> I think join is the better for implementation :P
14:48 cschneid_ joined
14:48 <merijn> "return >=> f = f = f >=> return"
14:48 <Cale> Actually, the associativity law is kind of neat to look at do-notation
14:48 <Cale> in*
14:49 <erisco> well sure, because you can get >>= from fmap and join, and so then you just substitute into the >>= laws
14:49 <merijn> Cale: Both associativity and identity of return are nice with >=>
14:49 <shapr> Is there comonad notation similar to do notation?
14:49 <Cale> merijn: I know :)
14:49 cdg_ joined
14:49 <merijn> erisco: Yes, but that doesn't make the laws nicer to read/easier to understand
14:49 <freeside> nbro: http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf
14:49 <shapr> :t (>=>)
14:49 <lambdabot> Monad m => (a -> m b) -> (b -> m c) -> a -> m c
14:49 <erisco> I said I like join for the implementation
14:49 V3 joined
14:49 <erisco> sits in my head better to think about m (m a) -> m a rather than bind
14:49 <merijn> erisco: >=> gives "return >=> f = f = f >=> return" and "(f >=> g) >=> h = f >=> (g >=> h)"
14:49 <Cale> Basically, it's telling us that we can chop pieces of a do-block out of the middle and make them into their own definition without affecting the result
14:50 gcross_ joined
14:50 <Cale> So it's what lets us refactor our code into smaller parts
14:50 marsam joined
14:51 <freeside> equational reasoning at the granularity of multiple expressions
14:51 <erisco> merijn, yes, that is nice because it has some mathematical familiarity
14:51 <merijn> It also avoids a lot of noise that makes things hard to understand
14:52 <Cale> nbro: Here's my little take on it: https://wiki.haskell.org/Monads_as_computation
14:53 augur joined
14:53 <nbro> ok, guys, I will see have time to read about your suggestions
14:53 <nbro> ;)
14:54 <freeside> yeah. see you in a year or so :)
14:54 Johannes13_ joined
14:54 <nbro> lol
14:54 Luke joined
14:55 <freeside> have you ever wanted to watch a movie, and then and gone and read the reviews for that movie, and then found yourself wanting to watch all the movies that were mentioned in those reviews first? yeah.
14:55 rgc joined
14:55 <Cale> and then and gone and read those movies' reviews first, and then the same thing happened?
14:56 <Cale> and eventually you realised that you just like reading movie reviews
14:56 <freeside> haha
14:57 <Rembane> You will save so much time!
14:57 alanb99 joined
14:57 alanb99 left
14:57 <freeside> and then you find yourself hanging out on IRC talking about movie reviews with other movie reviewers
14:57 <nbro> lol
14:57 <freeside> meanwhile there are people out there *actually making movies*
14:57 <Tuplanolla> That never happens.
14:58 <merijn> freeside: Some of are just here to slack while we wait for our programs to finish running :p
14:58 <mbrock> I asked a question on reddit for which some of you may have input: https://www.reddit.com/r/haskell/comments/5zjpbu/asking_the_type_system_questions/
14:58 yellowj joined
14:58 <Tuplanolla> There's no point in reading positive reviews and insightful negative reviews are really hard to come by.
14:59 <shapr> I don't watch TV, and rarely do I watch movies.
14:59 <ggVGc> I never run my programs
14:59 <ggVGc> if they compile, they're done, aren't they?
14:59 <Tuplanolla> That they are.
14:59 <shapr> BUT! I would still like to be able to do a join across IMDB and netflix available movies.
14:59 <ggVGc> I thought we were all just running our programs in the type checker
14:59 <ggVGc> isn't that the main part
14:59 Apocalisp joined
14:59 <mbrock> no, the main part is rendering them to LaTeX and admiring the beautiful PDF
14:59 steeze joined
15:00 <Tuplanolla> The point of dependent types is to finally allow the likes of us to actually run something.
15:00 darjeeling_ joined
15:00 <merijn> mbrock: So, there are people who've had this kinda idea before, but I'm not aware of any really advanced tooling for haskell to do this
15:00 <ggVGc> Tuplanolla: imagine what the next thing will be that you find out you need in order to make your dependent types programs actually do something
15:00 <ggVGc> looking forward to what that might be
15:00 <mbrock> merijn: okay. I'm kind of considering hacking something together without any formal rigor, basically a shell script that calls :t on everything and uses grep, or whatever
15:01 <Tuplanolla> Whats happens in the type system stays in the type system.
15:02 <freeside> well, in the Haskell tradition, some people write screenplays, then they go to conferences and give talks about those screenplays, and other people read those screenplays and write movie reviews about the movies that would have been made from those screenplays
15:02 wtetzner joined
15:02 doodlehaus joined
15:02 uncertainty joined
15:02 <freeside> sometimes people write frameworks and libraries to make it easier for people to make a specific movie within the genre of movies implied by the screenplay
15:02 <mbrock> "I've noticed that your play is simply an instance of a more general play discovered by a narrative theorist in 1932"
15:03 <freeside> however, this means that anyone who wants to actually make a movie, like nbro, first needs to read a dozen screenplays and a hundred movie reviews
15:04 zcourts joined
15:04 <freeside> the screenplays give vague directions about scene composition, and the reviews talk knowledgeably about cinematography, but none of them actually answer the question "how does this camera work?"
15:04 <nbro> what? actually I’ve already taken part in a few short moviews :D
15:04 czeq joined
15:04 wraithm joined
15:05 <erisco> merijn, careful on your first law there
15:06 <merijn> mbrock: Most notably Conor McBride's work on Epigram is working on getting things to be like a "dialogue" between compiler and programmer
15:06 <merijn> mbrock: You might also want to have a look at Peaker's work on Lamdu
15:06 <merijn> mbrock: http://www.lamdu.org/
15:07 <merijn> WHich is doing work along similar lines
15:08 carlomagno joined
15:08 <nbro> hey guys, here’s my length function for lists using the syntax I asked you about before: http://lpaste.net/353564
15:08 <nbro> :D
15:08 uglyfigurine joined
15:09 <ggVGc> freeside: and then it turns out, no one actually has a cinema that can play haskell screenplays
15:09 <mbrock> merijn: ok, looks cool! to contextualize a bit, I'm not so focused on the interactivity part, it's more that I want a reason to claim "only these functions can alter this part of the state" because then I can more easily justify the program's correctness. It's entirely possible that I should just rewrite the program in Agda/Idris
15:09 <ggVGc> so the movie you made isn't useful anyway
15:10 <freeside> :)
15:10 simukis__ joined
15:10 <erisco> nbro, well done :)
15:10 <merijn> mbrock: Ah, that's harder
15:11 coltfred joined
15:11 pleax joined
15:11 <merijn> mbrock: This is the sorta stuff people at the cutting/bleeding edge of programming languages like to try doing :)
15:11 <erisco> nbro, there is a simpler definition if you want to keep trying
15:12 <freeside> a good learning exercise now would be to express the same concept in half a dozen ways
15:12 <freeside> like, "do this without `not`"
15:12 <erisco> id x, id id x, id id id x, ... ;)
15:13 <freeside> "do this without `where`"
15:13 coot joined
15:13 <freeside> "do this without `null`"
15:13 <freeside> "move the `+ 1` to operate on the result of calling aux"
15:14 doodleha_ joined
15:14 <freeside> "give up and use `length` lolol"
15:15 <nak> looking at this monad law: (m >>= f) >>= g == m >>= (\x -> f x >>= g) specifically the (\x -> f x >>= g) part. what happens first? (f x) or (x >>= g) ?
15:15 Wizek_ joined
15:15 <freeside> "do this without a `where`"
15:15 <freeside> "do this without | guards"
15:15 <merijn> nak: Function application has higher precedence than infix operators
15:15 <ggVGc> `where` is the best
15:16 <nak> i suspect (f x) >>= g is the order it happens in
15:16 <nak> ok thank you merijn ^_^
15:16 mmn80 joined
15:16 <nak> merijn: is that true in all cases? are there infix operators with higher precedence?
15:16 <merijn> nak: Infix operators/functions (if you use `) have a precence of 0-9 (higher binds tighter)
15:16 <merijn> nak: Function application has precedence 10, record syntax has precedence 11
15:16 <ski> nak : yes, application binds tigher than any (other) infix operator
15:16 Bish joined
15:17 <erisco> turn it up to 11
15:17 <nak> lol
15:17 <tdammers> record syntax is the marshall guitar amp among haskell syntax constructs
15:17 <ski> (apart from a few special syntactic constructions, but those aren't user-defined operators)
15:17 <nak> how can we check the precedence of any particular operator?
15:17 <nak> eg $
15:17 <merijn> nak: In ghci you can write ":info ($)" and it'll tell you
15:17 <ski> in the interactor `:info ($)'
15:17 tumdedum joined
15:17 tumdedum joined
15:18 <merijn> The default precedence for operators is 'infixl 9'
15:18 <nak> infix 0
15:18 bollu joined
15:18 <nak> merijn: infixl meaning left associativity ?
15:18 <merijn> nak: That's essentially the entire trick behind $, lowest possible precedence :)
15:18 <merijn> nak: Yes
15:18 malc_ joined
15:19 <nak> and user-defined operators cannot be outside of infix 0-9 ?
15:19 <merijn> nak: Defining precedence of your own operators is as simple as putting 'infixl 6 *' (or whatever your operator is) in there
15:19 <merijn> nak: Right
15:19 <nak> sweet
15:20 <* nak> smiles and continues reading
15:20 al-damiri joined
15:20 xall joined
15:20 <merijn> nak: Although, to be specific, *no* operators can be outside infix 0-9, not just the user defined ones ;)
15:21 rps joined
15:21 <nak> merijn: ah ok thank you for the distinction
15:21 <freeside> "space" is function application -- how do i :i that?
15:21 <nak> merijn: (f x) has precedence of 10 but that's not an operator
15:22 <merijn> freeside: Space is not an operator, tbh
15:22 <nak> freeside: well space is not always function application
15:22 <freeside> i meant what nak just said
15:22 militie joined
15:22 <erisco> you have it wrong
15:22 <freeside> i have it wrong
15:22 <* nak> chortles
15:22 <erisco> it isn't the space, it is just the juxtaposition of two terms
15:22 <erisco> otherwise what is f x and f x and so on
15:22 urodna joined
15:23 <merijn> nak: There's no real encoding of precedence of application/record syntax, but it's specified so that it behaves the same as if it did have precedence
15:23 <nak> f apply apply apply x !
15:24 binu joined
15:24 Sigyn joined
15:24 plugin joined
15:24 hucksy joined
15:25 fendor joined
15:25 sidei joined
15:26 pleax joined
15:27 raycoll joined
15:27 faberbrain joined
15:28 <nak> how can i develop an intuition about >> vs >>= (re monads)
15:28 <nak> i understand Just 5 >> Just 4 will give Just 4
15:28 <nak> but when would such an operator be useful
15:28 <nak> it reminds me of const
15:29 <nak> :t (>>)
15:29 <lambdabot> Monad m => m a -> m b -> m b
15:29 <nak> :t const
15:29 <lambdabot> a -> b -> a
15:29 <nak> yeah this is like monad const
15:29 <nak> wait
15:29 <nak> no it's not
15:29 <nak> it's a -> b -> b, not a -> b -> a
15:30 halogenandtoast joined
15:30 <nak> ok now i'm dumbfounded. can someone provide useful example of >>
15:30 <erisco> putStrLn "hello" >> putStrLn "sailor!"
15:30 <nak> :t putStrLn
15:30 <lambdabot> String -> IO ()
15:30 <nak> my brain
15:31 Wuzzy joined
15:31 boccato joined
15:31 <merijn> nak: Well, usually for sorta short-circuiting
15:31 <nak> erisco: can we use an example with no side effect ?
15:32 eklavya joined
15:32 <brynedwa1ds> :t (*>)
15:32 <lambdabot> Applicative f => f a -> f b -> f b
15:32 <merijn> nak: Consider you compute "authorised :: Maybe ()" "authorised >> result" which results in result if it's Just, or Nothing otherwise
15:32 oisdk joined
15:32 edsko_ joined
15:32 <nak> oh that's interesting
15:32 <erisco> x <- get; put (x + 1) >> return (x * 2)
15:32 <erisco> I don't know, it just comes up now and then
15:33 <nak> erisco: is that ... state monad ?
15:33 eklavya joined
15:33 <erisco> yes
15:33 Bish joined
15:33 <erisco> there are lots of things that return m () and usually that follows with >> (or nothing)
15:33 capisce joined
15:34 <merijn> nak: Also in parsers
15:34 <nak> ok thanks ^^
15:34 mson joined
15:34 <merijn> nak: "parsePrefix >> parsePartICareAbout"
15:34 <merijn> nak: You still wanna parse the prefix, but don't care about dropping it
15:34 minn joined
15:35 <erisco> it is the monad version of *>
15:35 <nak> erisco: yeah i see that brynedwa1ds mentioned that
15:35 <merijn> nak: >> basically keeps the monadic context/effects/whatever you wanna call it, but drops the result on the floor
15:35 MoALTz joined
15:35 <nak> merijn: cool. i'm sure i'll gather an intuition when i see it more in reading other code
15:35 <nak> i'll use that as my base understanding for now
15:36 <erisco> :t ($>)
15:36 <lambdabot> error:
15:36 <lambdabot> • Variable not in scope: $>
15:36 <lambdabot> • Perhaps you meant one of these:
15:36 <freeside> isn't it more like monad seq?
15:36 <erisco> really? well that is around too
15:36 <erisco> :t fmap . const
15:36 <lambdabot> Functor f => b -> f b1 -> f b
15:37 <merijn> :t (<$)
15:37 <lambdabot> Functor f => a -> f b -> f a
15:37 eyen joined
15:37 <merijn> Got the version wrong ;)
15:37 Levex joined
15:37 <merijn> > 'c' <$ Nothing
15:37 <lambdabot> Nothing
15:37 <merijn> > 'c' <$ Just True
15:37 <lambdabot> Just 'c'
15:38 dhil joined
15:38 dustmote joined
15:39 steeze joined
15:39 Claudius1aximus joined
15:39 mda1 joined
15:40 jmelesky joined
15:40 nopf joined
15:40 indiffernet joined
15:41 pharaun joined
15:42 Eliel joined
15:44 Dunearhp joined
15:44 besenwesen joined
15:44 CuriousErnestBro joined
15:45 _sg joined
15:45 tomboy64 joined
15:46 harfangk joined
15:46 thunderrd_ joined
15:47 caumeslasal joined
15:47 lattenwald joined
15:48 xall joined
15:49 bollu joined
15:52 Unhammer joined
15:53 ortmage joined
15:53 wraithm joined
15:54 wting joined
15:55 yellowj joined
15:55 SpinTensor joined
15:56 boombanana joined
15:56 arawack joined
15:57 bollu joined
15:57 skeet70 joined
15:57 Luke joined
15:57 oisdk joined
15:58 Dunearhp joined
15:58 naudiz joined
15:59 Ranhir joined
15:59 steeze joined
16:00 <mofasa_> for suppressing 'Defined but not used' for methods... Is it '-fno-warn-missing-methods' or '-fno-warn-missing-binds' ??
16:02 seangrove joined
16:03 <lyxia> mofasa_: when does such a warning occur?
16:03 CoconutCrab joined
16:04 <mofasa_> lyxia: ghc-mod reports for top level functions that are not used
16:05 <lyxia> "Defined but not used" sounds more like a -Wunused-binds warning than a missing-something
16:05 theelous3 joined
16:05 zdenal joined
16:05 danharaj joined
16:06 <lyxia> mofasa_: Okay thats -Wno-unused-top-binds (and implied by -Wno-unused-binds)
16:06 gcross_ joined
16:06 rgr joined
16:06 <mofasa_> lyxia: alright. The info I could find online was all very old, i think the flags have changed in the past 5 years?
16:06 <lyxia> mofasa_: "method" usually refers to functions that are part of a type class.
16:06 <lyxia> which is why I was confused.
16:06 <lyxia> mofasa_: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/flags.html these docs are up to date
16:07 medicijnman joined
16:07 d3lxa joined
16:08 <mofasa_> Aah so implementations in 'instance xx where ..' are called methods, the rest functions? I got confused as well
16:09 uncertainty joined
16:09 <lyxia> that's how I use these words
16:10 Sonolin joined
16:11 a3Dman joined
16:11 <mofasa_> that makes sense to me. no-warn-missing-methods are probably for incomplete type class instances
16:11 raichoo joined
16:11 mattyw joined
16:12 Ring0` joined
16:13 albel727 joined
16:14 sz0 joined
16:15 unK_ joined
16:15 chrissl joined
16:15 wraithm joined
16:16 Yuras joined
16:16 JoshS joined
16:16 hackebeilchen joined
16:17 ccomb joined
16:17 V3 joined
16:18 dabukalam joined
16:18 Levex joined
16:18 locallycompact joined
16:20 <Rodenbach> One of the examples at https://hackage.haskell.org/package/lens-tutorial-1.0.2/docs/Control-Lens-Tutorial.html is this: shiftMoleculeX = over (atoms . traverse . point . x) (+ 1) -- where does traverse come from? Is this a function from the Control.Lens module?
16:20 Shatnerz0 joined
16:20 <lyxia> Data.Traversable
16:21 <Rodenbach> lyxia: thx
16:21 <lassulus> Is v
16:21 <lassulus> ups
16:21 <Tuplanolla> Note that `traversed` is elsewhere, Rodenbach.
16:22 cdg joined
16:22 Glooomy joined
16:22 desc joined
16:22 robotroll joined
16:24 <mohsen_> Hi. Can I use the tutorial prompt at haskell.org to practice lyah examples?
16:24 alfredo joined
16:24 noam_ joined
16:25 crosleyt joined
16:25 robotroll joined
16:26 vlatkoB joined
16:26 <Cale> mohsen_: You probably shouldn't -- it was acting up the other day, and it's pretty limited even when it's working properly. Just grab GHC.
16:27 the|auriscope joined
16:27 HaskellLord69 joined
16:27 robotroll joined
16:27 <mohsen_> Cale: There is no other ghci online?
16:27 b4ff3r joined
16:27 xaviergmail_ joined
16:28 oisdk joined
16:28 <Rodenbach> Tuplanolla: okay, traverse is different from traversed.
16:28 aminb joined
16:28 aminb joined
16:28 nshepperd1 joined
16:29 cjh` joined
16:29 glowcoil joined
16:29 naudiz joined
16:30 catsup joined
16:30 <Cale> mohsen_: Well, there are various other things which will run programs in a sandboxed environment, but I don't see why you'd want to bother with them when it's easy enough to install ghci and have it run fast on your own machine without time limits and sandboxes
16:31 Ptival joined
16:32 <mohsen_> Cale: Hmm you're right, off to install ghci, thanks.
16:32 gcross_ joined
16:33 osa1 joined
16:33 <Rodenbach> That Lens tutorial says: „[…] we can do a lot more with lenses than just get and set values […]”. Can you give some examples of what „a lot more” means?
16:33 dtornabene joined
16:34 <Tuplanolla> > over (iso ord chr) (+ 13) 'A'
16:34 <lambdabot> 'N'
16:35 CurryWurst joined
16:35 <Rodenbach> Tuplanolla: okay, that’s an interesting example.
16:35 mikecaruso joined
16:36 HarveyPwca joined
16:36 CurryWurst joined
16:36 pleax joined
16:36 Levex joined
16:36 thunderrd__ joined
16:38 koala_man joined
16:43 aarvar joined
16:43 Ayey_ joined
16:44 TheEpsylon joined
16:44 augur joined
16:45 <chenyu``> > :t over
16:45 <lambdabot> <hint>:1:1: error: parse error on input ‘:’
16:45 <chenyu``> :t over
16:45 <lambdabot> ASetter s t a b -> (a -> b) -> s -> t
16:46 yamadapc joined
16:46 glamas joined
16:46 Guest____ joined
16:46 ragepandemic joined
16:47 <glguy> Rodenbach: The power comes from being able to generalize operations e.g. mapAccumLOf, lengthOf, holesOf, elemOf, forOf
16:48 Detrumi joined
16:49 plugin joined
16:49 sidei joined
16:49 bluepixel joined
16:50 ParkeT joined
16:50 <ParkeT> Hi, guys.
16:51 tommd joined
16:51 urodna joined
16:52 cdg_ joined
16:52 anRch joined
16:52 <ParkeT> Is `ma >> mb` the same as `second <$> fa <*> fb ` where `second _ b = b`
16:52 <benzrf> ParkeT: yes
16:53 <benzrf> ParkeT: exercise: deduce this from the monad and applicative laws :)
16:53 <benzrf> (and the fact that the Applicative implementation needs to be equivalent to a certain one in terms of Monad)
16:53 strykerkkd joined
16:53 <ParkeT> Nice idea. I will. Thx
16:53 <benzrf> good luck
16:53 Gurkenglas joined
16:54 trism joined
16:54 <ParkeT> Bye ;)
16:54 <benzrf> ParkeT: oh, fyi
16:54 <benzrf> @src (>>)
16:54 <lambdabot> m >> k = m >>= \_ -> k
16:54 <benzrf> this should be useful
16:55 koala_man joined
16:55 <ParkeT> Lambdabot. hmmm. Nice :) Let me try
16:55 <ParkeT> @src a >>= b
16:55 <lambdabot> Source not found. I've seen penguins that can type better than that.
16:55 <ParkeT> oups
16:55 pera joined
16:55 <ParkeT> @src (>>=)
16:55 <lambdabot> Source not found. Wrong! You cheating scum!
16:55 <benzrf> ParkeT: that's per-instance, of course
16:56 <benzrf> (also, @src uses a static pre-written database, so it's very limited)
16:56 <ParkeT> Oh. Ok
16:56 wavewave joined
16:57 <chenyu``> benzrf: how do you know that? is there an article introduce lambdabot?
16:57 <benzrf> chenyu``: i've just learned it from other people saying so after hanging out for long enough in the channels :)
16:57 <brynedwards> stupid lens question: how do I do this without the map? map (view _2) [(1, 2), (3, 4)]
16:58 <brynedwards> I'm using amazonka which uses lenses for everything
16:58 <glguy> You wouldn't do that without a map
16:58 <Tuplanolla> There's `each`, but why?
16:58 <glguy> You can hack it in like: toListOf (folded . _2)
16:58 <Rembane> brynedwards: fmap or list comprehension?
16:58 <benzrf> brynedwards: traverse
16:59 <benzrf> > toListOf (traverse . _2) [(1, 2), (3, 4)]
16:59 <lambdabot> [2,4]
16:59 <Rembane> brynedwards: foldr if you really hate maps
16:59 <benzrf> ah, glguy just said that... oops :)
16:59 Ayey_ joined
17:00 <brynedwards> Well what I have is 'let logKeys = map (view oKey) (lrs ^. lrsContents)'
17:01 <benzrf> oh jeez
17:01 <brynedwards> And oKey is a lens, and (lrs ^. lrsContents) is [Object]
17:01 <benzrf> (^.) is the same as view
17:01 <benzrf> you're nesting views there! just compose the lenses
17:01 <brynedwards> From here https://hackage.haskell.org/package/amazonka-s3-1.4.5/docs/Network-AWS-S3-ListObjectsV.html#v:lrsContents
17:01 <brynedwards> I know it's really dumb :'(
17:01 <benzrf> well... why not just compose the lenses, if you know?
17:02 neophytes joined
17:03 pleax joined
17:03 bodisiw joined
17:04 <neophytes> Can anyone explain steps 5 and 6 here: http://i.imgur.com/1grOkPu.png -- λz(λn.z)((λp.p)z)) to λz.z -- book says bind n to ((λp.p)z)), but that confuses me since there is no other n in the expression other than λn which is at the head
17:04 tfc joined
17:05 Ayey_ joined
17:06 codesoup joined
17:07 Cthalupa joined
17:07 hvr joined
17:07 hvr joined
17:08 <benzrf> neophytes: hmm, this does look to me like it should become (\n.z)
17:08 meoblast001 joined
17:09 xall joined
17:10 <neophytes> benzrf: yeah thats what i thought -- since λz and z match up in λz(λn.z) so set z=((λp.p)z)=z and it becomes λn.z
17:10 the|auriscope joined
17:10 <lyxia> neophytes: (λn. z) (...) -> z in one step
17:11 Luke joined
17:11 <lyxia> It's not (λz. (λn. z)) ((λp. p) z) but λz. ((λn. z) ((λp. p) z))
17:11 wraithm joined
17:12 <neophytes> oh ok
17:12 fizruk joined
17:12 moongazer joined
17:12 Swizec joined
17:13 <benzrf> aha
17:13 ziocroc joined
17:13 meff` joined
17:13 <neophytes> i'm confused because the book writes it as λz. (λn. z) ((λp. p) z) in step 5
17:14 sssilver joined
17:14 logcat joined
17:15 <lyxia> Right that's how it's usually written with minimal parentheses
17:15 <lyxia> lambdas group as far to the right as possible
17:15 <neophytes> so Az "quantifies" over the entire expression?
17:16 <nshepperd> it's the same as λz. x y
17:16 <neophytes> λz. ((λn. z) ((λp. p) z)) -- how do i proceed from there?
17:16 <nshepperd> except that x is (λn. z) and y is ((λp. p) z)
17:17 Ayey_ joined
17:17 <neophytes> there doesn't look like anything else i can do to λz. ((λn. z) ((λp. p) z))
17:18 Shatnerz0 joined
17:18 <neophytes> unless you say p:=z and then λz. ((λn. z)z)) -> (λn. z) ?
17:18 <nshepperd> beta reduce it
17:18 <nshepperd> apply (λn. z) to ((λp. p) z)
17:19 jshjsh joined
17:19 <benzrf> ahaha 'nshepperd' and 'neophytes' are the same length and same color in my client and both start with n, i didnt even notice at first it wasnt one person talking to themself
17:19 pleax joined
17:19 <nshepperd> muahaha
17:19 <neophytes> nshepperd: is that not just say p:=z and then λz. ((λn. z)z)) -> (λn. z) ?
17:19 <Tuplanolla> They're orange and red for me too, benzrf.
17:20 <benzrf> Tuplanolla: no, the're both purple for me
17:21 UserJosh joined
17:21 <neophytes> λz. ((λn. z) ((λp. p) z)) -> p:=z -> λz. ((λn. z) (z)) -> λn. z -- is that right?
17:21 <nshepperd> not quite
17:22 <nshepperd> what do you get when you beta reduce (λn. z) z?
17:22 <neophytes> i dont understand what to do then.
17:22 <neophytes> you cant reduce (λn. z) z as you wrote it
17:22 <neophytes> since z is a free variable
17:22 <nshepperd> sure you can
17:22 <johnw> blue and fuschia here :)
17:23 <nshepperd> substitute z in for n
17:23 <neophytes> (λn. z) z as written contains z as a free variable
17:23 <Adluc> == (\n -> z) x
17:23 <neophytes> which z are you subsituting? (λn. z1) z2
17:23 <Adluc> == z
17:23 <neophytes> in my expression
17:23 <nshepperd> neophytes: they're the same z
17:24 Destol joined
17:24 Seabed joined
17:24 <neophytes> im not followig
17:25 <neophytes> steps 5 to 6 make no sense to me
17:25 Seabed left
17:25 <neophytes> based on what the book wrote (which isnt much to that point) I do not know the rules to proceed from step 5 to 6
17:25 <nshepperd> neophytes: (λn. z) is a constant function. it returns z no matter what you apply it to
17:25 Ayey_ joined
17:25 <neophytes> ok
17:26 Renesat joined
17:26 <nshepperd> so now apply (λn. z) to z
17:26 <neophytes> the book says if there is a free variable you cannot do a replacement
17:26 <neophytes> z is a free variable
17:26 <neophytes> lambda only quantifies n
17:27 <neophytes> im not seeing how youre moving from 𝜆𝑧((𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧)) step
17:27 <nshepperd> :/
17:27 <nshepperd> I don't understand why the book would say that
17:27 <neophytes> so what are the actual rules
17:27 <nshepperd> beta reduction works fine with free variables
17:28 <neophytes> o i c
17:28 pwnz0r joined
17:28 leat joined
17:28 cdg joined
17:28 <neophytes> e.g. book writes: Note that alpha equivalence does not apply to free variables. That is, 𝜆𝑥.𝑥𝑧 and 𝜆𝑥.𝑥𝑦 are not equivalent because 𝑧 and 𝑦 might be dif- ferent things. However, 𝜆𝑥𝑦.𝑦𝑥 and 𝜆𝑎𝑏.𝑏𝑎 are equivalent due to alpha equivalence, as are 𝜆𝑥.𝑥𝑧 and 𝜆𝑦.𝑦𝑧 because the free variable is le alone.
17:28 <lyxia> It's talking about something else
17:28 <johnw> is everything Typeable by default since GHC 7.8, or is it just possible to auto-derive Typeable since then?
17:29 <lyxia> johnw: everything is Typeable
17:29 faberbrain joined
17:29 <neophytes> ok
17:29 <brynedwards> I still don't understand...with a lens, what's the "correct" way to apply a getter to a list I guess...?
17:30 <neophytes> so what are the steps for reducing: 𝜆𝑧((𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧))
17:30 <neophytes> this is one of the very first problems im looking at
17:30 <nshepperd> neophytes: right, it's saying there that you can't rename free variables. you can't decide that z is now called w. but you can still beta reduce
17:30 <johnw> brynedwards: you mean, apply a getter to every element of a list?
17:30 <johnw> > [(1,2),(3,4)] ^.. traverse._1
17:30 <lambdabot> [1,3]
17:30 guiben joined
17:31 <neophytes> nshepperd: ok, so step-by-step how do you reduce 𝜆𝑧((𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧)) then
17:31 <chenyu``> :i toListOf
17:31 <chenyu``> :t toListOf
17:31 <nshepperd> neophytes: apply (λn.z) to ((\p. p) z)
17:31 Levex joined
17:31 <lambdabot> Getting (Endo [a]) s a -> s -> [a]
17:31 <nshepperd> neophytes: you get z[n := ((\p. p) z)]
17:31 <chenyu``> @src toListOf
17:31 <lambdabot> Source not found. Just what do you think you're doing Dave?
17:31 sobaken joined
17:31 wildlander joined
17:31 <nshepperd> that is "z" with n replaced by "((\p. p) z)"
17:32 <nshepperd> neophytes: however "z" doesn't contain "n" anywhere, so that's simply "z"
17:32 boccato joined
17:32 <nshepperd> so now you have λz. z
17:33 <brynedwards> johnw: I have two lenses (from amazonka-s3) 'lrsContents :: Lens' ListObjectsVResponse [Object]' and 'oKey :: Lens' Object ObjectKey'
17:33 <neophytes> i dont follow your notation. im trying to parse it 𝜆𝑧((𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧)) -> apply (λn.z) to ((\p. p) z) traslates to: (𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧)) -> z[n := ((\p. p) z)] dont know what this means
17:33 <brynedwards> and I want to get to [ObjectKey] from ListObjectsVResponse
17:34 <nshepperd> z[n :=
17:34 <Rodenbach> About the molecule example from the Lens tutorial again: https://hackage.haskell.org/package/lens-tutorial-1.0.2/docs/Control-Lens-Tutorial.html
17:34 <Rodenbach> What if we had 200 Atoms stored in a molecule, and we wanted to update the nth? How would one do that?
17:34 <Cale> neophytes: it just means that you're meant to substitute n for ((\p . p) z) in what came before
17:34 <Cale> neophytes: However, since there are no occurrences of n, there's nothing to do
17:35 <neophytes> ok
17:36 <neophytes> 𝜆𝑧((𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧)) -> n:=((𝜆𝑝.𝑝)𝑧)) -> there are no n's to apply this sub to -> then the next step?
17:36 <brynedwards> I tried "(lrs :: ListObjectsVResponse) ^.. lrsContents . oKey" but that doesn't seem to work
17:36 <brynedwards> I mean "(lrs :: ListObjectsVResponse) ^.. lrsContents . traverse oKey"
17:36 <nshepperd> neophytes: so, (λn.z)((λp.p)z) -> z
17:37 <brynedwards> I'm assuming this involves a getter...
17:38 <neophytes> z:= (λn.z)((λp.p)z) and replace all occurnaces of z with (λn.z)((λp.p)z) in 𝜆𝑧((𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧)) or do you mean 𝜆𝑧((𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧)) reduces to z
17:38 <nshepperd> neophytes: I mean that (λn.z)((λp.p)z) reduces to z
17:38 <nshepperd> neophytes: as we just established by beta reduction
17:39 <nshepperd> neophytes: which means that λz. (λn.z)((λp.p)z) reduces to λz.z
17:39 asmyers joined
17:40 coltfred joined
17:40 <neophytes> ((𝜆𝑝.𝑝)𝑧)), p: = z -> z -- is that wrong?
17:41 <neophytes> i am not filling in the piece from 𝜆𝑧((𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧)) -> z
17:41 <nshepperd> ((λp.p)z) also reduces to z, yes, but you don't need to know that
17:41 <dmwit> brynedwards: `lrsContents . traverse . oKey`?
17:41 <nak> ok so i'm trying to understand runIdentity in the Identity monad. first of all, i don't even know how to construct a value compatible with Identity. ideas there?
17:41 <dmwit> Rodenbach: `at n`?
17:41 cfricke joined
17:42 <dmwit> Disclaimer: I have only used lens for a few hours total.
17:42 pleax joined
17:42 <dmwit> nak: `Identity` is the constructor for the `Identity` type.
17:42 <neophytes> I understand: 𝜆𝑧((𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧)) and saying n:= ((𝜆𝑝.𝑝)𝑧)) , and not being able tp do that since n doesn't appear anywhere, so then im stuck back at 𝜆𝑧((𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧))
17:42 <nak> i'm trying to interact with Identity in my terminal. things like :t Identity and :t runIdentity say data constructor not in scope
17:42 <dmwit> > Identity 3 :: Identity Int
17:42 <lambdabot> Identity 3
17:42 <neophytes> youre saying set z: = (𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧)
17:42 <neophytes> in 𝜆𝑧((𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧))
17:42 <lyxia> nak: you must import the module Data.Functor.Identity first
17:42 <dmwit> nak: import Control.Monad.Identity
17:42 <nak> ah
17:43 <nak> ok so newbie question
17:43 freeside joined
17:43 <nak> how would i know i need to do that?
17:43 <nak> well
17:43 <dmwit> Hoogle it.
17:43 phyrex1an joined
17:43 sgflt joined
17:43 <nshepperd> neophytes: let's take a simpler example. what is ((λn. z) w)?
17:43 <nak> how would i know that specific module
17:43 <dmwit> https://www.haskell.org/hoogle/
17:43 <dmwit> ?hoogle Identity
17:43 <lambdabot> module Data.Functor.Identity
17:43 <lambdabot> Data.Functor.Identity newtype Identity a
17:43 <lambdabot> Data.Functor.Identity Identity :: a -> Identity a
17:43 <neophytes> ((λn. z) w)
17:43 structuralist joined
17:43 <neophytes> nshepperd: ((λn. z) w) is ((λn. z) w)
17:43 <nshepperd> neophytes: no, you can beta reduce it
17:44 <nak> dmwit: and how do i know which of those is correct for me ?
17:44 <neophytes> how?
17:44 <dmwit> nak: They are all correct. =)
17:44 <nshepperd> neophytes: set n := w
17:44 <nak> I see Control.Monad.Identity and Data.Functor.Identity
17:44 <nak> do i need to import both if i want to use Identity as Functor and as Monad ?
17:44 <neophytes> okay so i set n:=w but there are no n's to sub it in
17:44 <neophytes> ((λn. z) w) -- the only n is at the head
17:44 <neophytes> there are no n's in the body
17:44 fizruk joined
17:44 <nshepperd> neophytes: yep
17:44 <dmwit> nak: Both will work. You can see from `Control.Monad.Identity`'s source that it is just re-exporting `Data.Functor.Identity`'s newtype.
17:45 <neophytes> so i cannot sub n anywhere
17:45 <nshepperd> neophytes: so the result is just the body, unaffected, right?
17:45 <neophytes> yes
17:45 <neophytes> so ((λn. z) w) is ((λn. z) w) no?
17:45 <nak> dmwit: ok
17:45 <nshepperd> neophytes: the result is z
17:45 <neophytes> oh i see
17:45 <dmwit> nak: http://hackage.haskell.org/package/mtl-2.2.1/docs/src/Control.Monad.Identity.html
17:45 tristanp joined
17:45 <dmwit> nak: Which I reached by Hoogling; then clicking `Control.Monad.Identity`; then clicking "source" in the top right.
17:46 <neophytes> i did not know it worked this way
17:46 desc joined
17:47 <nshepperd> neophytes: so ((λn. z) w) reduces to z
17:47 <nak> in prelude: import Control.Monad.Identity Error: Could not find module ‘Control.Monad.Identity’
17:47 <nak> :(
17:48 <dmwit> From the documentation, you can see this is in the `mtl` package. If you don't have this installed, you can install it with `cabal install mtl`.
17:48 <nshepperd> neophytes: then what is ((λn. z) ((λp.p)z))?
17:48 <dmwit> That will install it locally to your user, which is the recommended way.
17:48 <neophytes> n:= ((λp.p)z), but there is no n to replace it with. so it becomes z?
17:49 <nshepperd> neophytes: yep :)
17:49 <neophytes> ahhh i see
17:49 eschnett joined
17:49 <neophytes> 𝜆𝑧(𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧) -> 𝜆𝑧.z is correct then
17:50 tfc joined
17:50 yellowj joined
17:51 <nshepperd> just so
17:51 <nak> dmwit: the All About Monads (https://wiki.haskell.org/All_About_Monads) mentions that some monads are available in Prelude
17:51 <neophytes> ok thank you very much for your patience and taking the time to explain this to me so well
17:51 <nak> so Identity just isn't in Prelude then?
17:51 <neophytes> i highly apperciate it
17:52 <dmwit> nak: Correct.
17:53 wraithm joined
17:54 ner0x652 joined
17:54 shesek joined
17:54 <dmwit> nak: A comment I made to somebody else the other day might be helpful to you, too: a module (like `Prelude`, `Control.Monad`, or `Data.Functor.Identity`) is a collection of code snippets. A package (like `base`, `mtl`, or `parsec`) is a collection of modules. Cabal and stack also have a notion of a project, which is a collection of packages.
17:55 <dmwit> nak: `mtl` is a package with several modules that each define new monads, and so is quite a popular dependency.
17:55 ryantrinkle joined
17:56 <nak> dmwit: so is there a list of modules that ships with Haskell? or is it only Prelude?
17:56 <dmwit> Actually, there is a list of packages that ship with GHC. =)
17:57 <dmwit> So no, it is not only Prelude.
17:57 <nak> and sorry if this is starting to sprawl into too many questions: if i cabal install mtl, does that happen at the project level, or does it install "globally", ie available to any project?
17:57 <dmwit> If you run `ghc-pkg list --global`, you will see the packages that shipped with your version of GHC.
17:57 <dmwit> `cabal install mtl` will install into your user package database. Other cabal projects that list `mtl` in their dependencies will be able to use it without further effort.
17:58 boombanana joined
17:58 <ryantrinkle> does anyone have an idea of the performance impact of using ContT over IO (compared with straight IO)?
17:58 fizruk joined
17:58 <dmwit> However, there are some gotchas that have led people to prefer cabal sandboxes, which let you install packages local to a particular directory.
17:59 <dmwit> I wonder if there is a wiki page about the devops side of things.
17:59 <nak> dmwit: yeah i do a lot of node dev and packages are almost alwyas locally installed to a project
17:59 <nak> helps resolve version conflicts across various projects
17:59 <nak> i'm okay doing whatever is most common amongst haskell community for now tho
18:00 betawaffle joined
18:00 <dmwit> That is indeed the issue that sandboxes address.
18:00 <orion> What are proof assistants like Coq and Adga used for, and if I'm not a mathematician, do these tools have a use case?
18:00 <dmwit> So the pattern for a new project is to make a directory and run `cabal sandbox init`. Then `cabal install mtl` will install `mtl` to that sandbox only.
18:01 <suppi> nak: have read much but warm suggestion to use stack :)
18:01 Luke joined
18:01 <suppi> haven't
18:01 <Cale> orion: Well, observing aspects of what might be the future of programming languages?
18:02 <Cale> orion: Also, you *can* write software with them, and prove theorems about it
18:02 <Cale> orion: There is, amazingly, a pretty complete end-to-end C compiler in Coq
18:02 <orion> Cale: Why is it amazing?
18:02 <suppi> nak: this guide is pretty thorough i think http://howistart.org/posts/haskell/1/
18:03 replay joined
18:03 <Cale> orion: Because Coq is really not geared toward practical application development
18:03 <nak> suppi: thank you. i put it on my list to "learn stack", gonna stick to my "problem" at hand for now
18:03 <dmwit> orion: Some of my coworkers have used Coq to help develop a model of vote tabulation and formally verify that an implementation adheres to the protocol.
18:03 <nak> suppi: so many things to learn!
18:03 tommd joined
18:04 <orion> Cale: I see. Isn't Haskell the future of programming languages? What does Adga have that Haskell won't (eventually) have?
18:04 <dmwit> orion: So it does see some use. But it is also a very expensive development model, because proved-correct code is much more difficult to write.
18:04 <Cale> orion: Actual dependent types. I would say Haskell is the present of programming languages.
18:04 <suppi> nak: is your problem "i don't have the package i want installed"?
18:04 <suppi> i may have misunderstood, sorry
18:04 <nak> suppi: no that is definitely my problem lol
18:04 <orion> Cale: Why can't Haskell have dependent types? Does System F now allow for it?
18:05 ryantrinkle left
18:05 <nak> suppi: i ran "cabal install mtl"
18:05 <Cale> orion: Well, System F isn't dependently typed
18:05 <dmwit> orion: System F indeed does not support dependent types.
18:05 <orion> :(
18:05 <geekosaur> orion, dependent types break things that people tend to rely on.. .like type inference
18:05 <suppi> nak: then the simplest solution is to learn stack from the guide i linked :)
18:05 sanitypassing joined
18:05 <nak> suppi: ok ok
18:05 deltawaffle left
18:05 <dmwit> nak: You should already have it if you ran `cabal install mtl`.
18:05 <Cale> geekosaur: Yeah, well, there's probably stuff you can do in practice to help that along.
18:05 connrs joined
18:05 <dmwit> nak: Of course feel free to learn `stack` if you like.
18:06 <dmwit> nak: `stack` vs `cabal` tends to evoke strong opinions from people.
18:06 <Cale> geekosaur: and it's also worth noting that dependent types also *enable* term inference to a large extent
18:06 <nak> i figured it might have such an effect
18:06 <nak> like bower vs npm vs yarn
18:06 <nak> people love their package managers
18:06 <orion> dmwit: How exactly does this development model work? In other words, someone hires me to build a "thing", and I want to use Adga or Coq to prove that my deliverable (written in, say, Haskell) is correct.
18:06 <suppi> i don't love stack nor hate cabal btw, i use both :)
18:07 <dmwit> orion: I think a common way is to implement it in Coq and extract that code to Haskell or ML.
18:07 <* geekosaur> would be less annoyed at stack if he didn;t keep hitting blogs that very carefully make sure to only mention fpco-run sites/web pages
18:07 <Cale> orion: But also, Haskell's syntax would have to change a bunch to make dependent types not be shitty, I feel
18:07 ubsan_ joined
18:07 <Cale> in ways that would break lots of libraries
18:07 <Cale> Like, currently types and terms in Haskell live in entirely separate namespaces
18:07 <orion> I see.
18:07 <brynedwards> dmwit: Thank you =)
18:07 <Cale> and we reuse identifiers at both levels all the time
18:07 mizu_no_oto_work joined
18:08 electrostat joined
18:08 Ayey_ joined
18:08 <Cale> GHC is sort of edging toward dependent types, but what's there is kinda awkward to use relative to something that was designed for it from the start
18:09 zcourts joined
18:09 <geekosaur> ...and fpco didn;t go out of their way to make said pages look exactly like the official ones except they only mention fpco which is clearly and obviously presented as the maintainer of everything worthwhile involving haskell
18:09 <geekosaur> it feels like a hostile takeover attempt
18:09 BlueRavenGT joined
18:09 <nak> fwiw i have ghc-8.0.2 cabal-install-1.24.0.2 and stack-1.3.2 (hpack 0.15.0), are these versions current enough? (all were installed through homebrew on osx)
18:10 xall joined
18:10 <MarcelineVQ> nak: looks pretty recent to me
18:11 oisdk joined
18:11 <nak> MarcelineVQ: thx ^^
18:11 <dmwit> nak: Those were all released in the last four months.
18:11 <dmwit> So quite recent.
18:11 <Cale> orion: But yeah, Coq in particular has been around a fairly long time actually -- some bits of it feel older than Haskell (its term syntax especially is clearly influenced by older MLs)
18:12 <Cale> orion: But yeah, dependent types let you say a whole lot more than you can say with Haskell's types
18:12 <orion> dmwit: Could you contrive an example of a project that, if just done in Haskell could lead to unintended consequences, but if I had only done it in Coq first I would be fine?
18:12 <dmwit> orion: You can write bugs in any project.
18:13 <orion> Right. Therefore, I am not convinced of the value proof assistants bring to the table.
18:13 <Cale> Note that you can still write bugs in Coq or Agda, it's just you have more tools for saying what you mean and having the computer check things.
18:13 <Cale> For example, you might want to express that a sort function actually sorts a list.
18:13 <JuanDaugherty> Coq is general purpose now?
18:14 <Cale> JuanDaugherty: Well, it is with sufficient heroism :)
18:14 <Cale> It's certainly not aimed at being general purpose for the most part
18:14 <JuanDaugherty> (as distinct from ocaml)
18:14 <dmwit> orion: Bugs are much, much less common in proved-correct Coq projects, because usually you don't create the exact same bug in both the spec and the implementation; and because the machine checks the correspondence between the spec and the program.
18:15 <dmwit> orion: For example, famously fuzzers tried out all the major C implementations and found hundreds of bugs in gcc and clang, but only two in compcert -- and they were in the unverified part of compcert.
18:15 subttle joined
18:15 neophytes joined
18:15 <JuanDaugherty> thinking that all computing needs to be proofs is ... .
18:15 <JuanDaugherty> (cast as you will)
18:16 <Cale> orion: Once you can have types which are parameterised by values, one of the first things you can do is to define a type which, given a type, and two values of that type, expresses the fact that those values are equal
18:16 <dmwit> If correctness is at a premium, I think the data very much support using Coq or the like.
18:16 whaletechno joined
18:16 <* JuanDaugherty> searches mind for a negative form of "mathesis"
18:16 sidei joined
18:17 <Cale> You do that by only giving the type a single constructor: Refl :: Id A x x
18:17 <dmwit> JuanDaugherty: yo' thesis
18:17 <JuanDaugherty> dmwit, lol
18:17 uglyfigurine joined
18:18 dhil joined
18:19 <Cale> orion: and that lets you describe equations between things, and if you can somehow (perhaps using a recursive definition) define something of type Id A x y, then you know that x and y must be equal
18:19 <orion> I'm completely unfamiliar with proof assistants. Let's say I am creating some Pokemon-style card game. Given all the rules and all the defined cards, could a proof assistant inform me of any loopholes in the rules?
18:19 <jle`> you'd have to define what loophole means
18:19 <Cale> If you can say what a loophole is, you could prove that there are no loopholes
18:20 ccomb joined
18:20 <orion> Interesting.
18:20 <Cale> It probably won't be able to just *inform* you -- it'll still require work.
18:20 <Cale> But how much work will depend on the definition of loophole :)
18:21 <erisco> finding the right questions to ask and figuring out the model are the hard parts
18:21 <Cale> orion: You can basically do all of mathematics in Coq's type system
18:21 Luke joined
18:21 <Cale> So anything you can reasonably imagine writing a mathematical proof about is probably going to be fair game
18:21 <erisco> you can come write Idris code with me :3
18:22 <monochrom> Yeah, Idris is a much more gentle introduction.
18:22 <Cale> Yeah, Idris is another one we ought to be mentioning
18:22 <orion> Cale: Right, but I am not necessarily a mathematician. Business people give me money to solve their problems, and I want to provide a proven solution.
18:23 xaviergmail_ joined
18:23 <erisco> well it doesn't come for free. There is substantial cost to having more elaborate types
18:24 <erisco> when you consider the practical effect of bugs it may not be worth it
18:25 <erisco> if it is safety, finance, security, and things of this nature then it is well deserved
18:25 <erisco> but if you're tasked with adding a popup box when the user clicks a button on the web page...
18:25 cagri joined
18:25 <JuanDaugherty> yeah bebugging used to be an engineering technique back when software engineering was a thing
18:25 <orion> erisco: I am in the financial payment industry.
18:26 Berra joined
18:27 pfurla joined
18:27 <bodisiw> i always want to formalize business rules and SAT check them
18:27 <bodisiw> but it has never worked out :-)
18:27 <orion> bodisiw: Why?
18:27 <bodisiw> because i want business rules to be consistent?
18:28 <orion> Just force your customers to be 100% consistent. That's a strategy for success.
18:28 <reactormonk> How can I you get the primitive type out of a newtype?
18:29 Ferdirand joined
18:30 <domenkozar> is it possible to install older stack version on windows?
18:30 <StoneToad> reactormonk: you mean like unFoo (Foo x) to get x?
18:31 <reactormonk> StoneToad, newtype Foo = Foo Text -- get Text from Foo. Yeah.
18:31 <cocreature> reactormonk: get the type or get the value of that type?
18:31 Noldorin joined
18:31 <reactormonk> cocreature, value.
18:32 <cocreature> reactormonk: you can define newtype Foo = Foo { unfoo :: Text }
18:32 <StoneToad> you could also define the same function manual as unFoo (Foo x) = x
18:32 <orion> dmwit / Cale: Do you know of any case studies of proof assistants in business? I.e. "Our business had to do a /thing/ and Coq helped us do the /thing/!"
18:33 <StoneToad> manually*
18:33 jathan joined
18:34 Swizec joined
18:34 cagri left
18:34 <jlouis> shapr: w.r.t. parsing binary data in Haskell: Use an applicative instance to define how to decompose the stream. This is what I did back in the day, but I've been out of the loop for too log
18:34 <erisco> I'd be interested to hear as well
18:34 <erisco> I don't think there is much uptake, otherwise I'd expect to see more activity
18:34 <monochrom> reactormonk: Also pattern matching. You do have the data constructor "Foo" (the second one) to match against.
18:35 boccato joined
18:35 oisdk joined
18:35 <shapr> jlouis: ok, thanks
18:35 <jlouis> shapr: the key takeaway from Erlang is that binary matching is very good as a way to handle complex binary protocols. And it is fast enough in practice to work out
18:35 <reactormonk> monochrom, yeah, that would be the manual definition StoneToad mentioned.
18:36 <erisco> you need a team of highly educated people to use the tools
18:36 Miroboru joined
18:36 <monochrom> But I had "case ... of Foo t -> ..." in mind.
18:36 <jlouis> shapr: also, look up something like Meredith Patterson's work on "Hammer". Parsing should be left to combinator libraries
18:36 <jlouis> shapr: for security reasons
18:36 <erisco> and if you're not one of those people then how are you going to be convinced to seek out those hires
18:37 tlevine joined
18:37 <erisco> versus looking at what everyone else is doing
18:37 <orion> erisco: Speaking to me?
18:37 <jlouis> erisco: from lots of real-world Erlang QuickCheck experience: the load factor is 3-5 times the development time on QC models. But upshot is that you have almost no maintenance afterwards on the code
18:37 <erisco> yes
18:37 vydd joined
18:38 a3Dman joined
18:38 <orion> erisco: Define "highly educated".
18:38 <jlouis> IMO something like Coq has a larger load factor than that. You need something where the cost/benefit analysis pans out to an advantage
18:39 <* monochrom> grins. Adding numbers used to be exclusive to the highly educated too. :)
18:39 <erisco> if you were to learn everything just from school then you need graduate education
18:40 <jlouis> In short: measure a project as a whole, not just to the point where the system is deployed, and formal methods tend to win in the long run. Especially for things which are 1) Used by lots of people. 2) Correctness sensitive.
18:40 <erisco> jlouis, that is interesting. so if it is 3-5x cost to get something out the door that's a tough sell
18:40 <jlouis> erisco: yes, unless you happen to work in part of the system where this is a benefit
18:40 <cocreature> erlang quickcheck is still testing not verification, no?
18:40 <monochrom> It is very much short-term very long-term. (Under an assumption.)
18:40 <jlouis> It is just testing, indeed
18:41 <cocreature> the cost of proving things is a lot higher
18:41 <jlouis> yes. A load factor of 10-30 is not unheard of
18:41 <monochrom> (The assumption: The pro-short-term people intend good rather than intend scam.)
18:41 <jlouis> It can be improved if you can redesign the system as you go along with the proof
18:41 tig_ joined
18:41 <jlouis> same for QC
18:42 <erisco> you want to sell early so you have income
18:42 plugin joined
18:42 <jlouis> I did the Erlang QC model for the "maps" feature (HAMTs) in Erlang. We found around 10-15 bugs, about 5 of them serious
18:42 <erisco> not so early that everyone hates you, but not so late that you go bust
18:42 Ayey_ joined
18:42 marsam joined
18:42 <jlouis> And they would have had impact on a lot of people since this is part of the stdlib
18:43 wraithm joined
18:43 <jlouis> Attack something with Money, or something where Nuclear fallout happens on error
18:43 <jlouis> Or planes falling from the sky
18:43 <jlouis> Or Mars Reentry happening at light speed
18:44 <cocreature> maybe we’ll figure out automating formal verification too a larger degree than we can atm at some point in the future :)
18:44 <jlouis> Distribution protocols are also notoriously hard to get right
18:44 <jlouis> TLA+ the hell out of those, etc
18:45 <jlouis> Another point is that there is no liability in software, so the sky doesn't fall when you mess up. If we had more liability, we would probably standardize on components where it is more likely to test them
18:46 <jlouis> The current world of ${STARTUP} and move fast and break things isn't particularly amenable to formal methods, except for a few places, IMO.
18:47 <jlouis> </rant> :)
18:47 grayhatter joined
18:48 <cocreature> tbh I don’t blame them. in a lot of cases the cost of formal verification is probably higher than the costs of bugs prevented by formal verification
18:48 plugin joined
18:48 electrostat joined
18:48 Ayey_ joined
18:48 Lord_of_Life joined
18:48 <monochrom> Things did and do get very complicated, subtle, and messy because of that. (Most software developers having not much liability.)
18:49 <monochrom> For example it is obvious to you that wrong firmware on a plane can cause plane crashes, and that when this actually happens whom to blame.
18:49 <jlouis> cocreature: yeah. QuickCheck is often easier. And it tend to find many of the same bugs. And it paves the way for a formal proof later as it is helping define the spec
18:50 Dembel joined
18:50 <monochrom> Not so obvious is CAD software used during the design of the plane can cause this too. And when this happen it is going to be a huge controversy.
18:51 <orion> monochrom: People getting killed in self-driving cars is another example.
18:51 <cocreature> often it is also simply unclear what you are even trying to verify. if you have some kind of isolated component where it is clear what it should do all is good, but good luck defining what your random webapp is supposed to do
18:52 zcourts joined
18:52 <jlouis> cocreature: this is what we tend to do with QuickCheck. We write a naive spec as a model and then we check if the system has this model. Tune the model. Repeat.
18:52 <jlouis> Suddenly it starts finding stuff the system shouldn't be doing
18:53 <jlouis> it isn't a proof, but the goal of QC is to find bugs
18:53 <jlouis> this finds bugs. Subtle bugs.
18:54 <cocreature> jlouis: what kind of systems are we talking about here? it’s relatively clear how to write a specification a data structure like HAMTs (it’s still a lot of work) but for some random webapp it’s less clear what it is even supposed to do
18:54 <jlouis> And it starts the road of having a spec in the first place
18:54 <cocreature> and sometimes the behavior changes too fast to justify the cost of having to adapt a spec at each step
18:54 <jlouis> HAMTs are easy actually. Your model is just [{K, V}] for key/value types
18:54 <monochrom> This is why I don't draw a line between testing and verification. Tests are proofs, too.
18:54 Ayey_ joined
18:55 subttle joined
18:55 <jlouis> Add to this that K's should be generated such that you have lots of HAMT collisions, and you have almost 100% code coverage
18:55 psychicist__ joined
18:55 <jlouis> monochrom: indeed! like types are.
18:56 <cocreature> don’t get me wrong, I work on formal verification myself. but I think there are legitimate reasons to not verify your code or even develop a spec
18:57 <jlouis> cocreature: https://github.com/jlouis/fuse https://github.com/jlouis/safetyvalve and https://github.com/jlouis/dht are three projects with QC models (all Erlang.. I ate an apple 10 years ago)
18:58 <jlouis> And yes, there is a lot of code that shouldn't be tested
18:58 ikke joined
18:58 dni joined
18:58 <cocreature> a friend of mine formally verified the correctness of Java’s dual-pivot quicksort implementation. it took him a full year and even then he had to rewrite the code in some places to make it more amenable to the tool he used
18:58 <jlouis> CompCert has this nice example where register allocation is written in (unverified) OCaml, but you can always verify the coloring when it comes back
18:59 coot joined
18:59 <jlouis> And there is lots of code which shouldn't be formally verified since it isn't worth doing so
19:00 infinity0 joined
19:00 conal joined
19:00 plugin joined
19:01 mda1 joined
19:01 <erisco> cocreature, I imagine he had to first model how Java works, and that would have been a chore
19:02 cyborg-one joined
19:02 <cocreature> erisco: nah, there are already tools that include formal models of subsets of Java and if you’re lucky your code only uses these subsets
19:02 nomeata joined
19:02 a3Dman joined
19:03 <geekosaur> parts of xmonad are formally verified (...thereby proving that you can't formally verify a sane UX)
19:03 <nomeata> Hi. I could need a little help playing around with dependent type ideas in Haskell. I have a 'data Tag = A | B', a
19:03 <erisco> I read a while ago that there was a bug found in Tim sort (Python's sort) when it was verified
19:03 <cocreature> yep
19:03 <cocreature> they used the same tool https://www.key-project.org/
19:03 <cocreature> they verified Tim sort in java
19:04 <cocreature> tim sort is used for objects and double pivot quicksort is used for primitive types iirc
19:04 <monochrom> I haven't learned dual-pivot quicksort, but it sounds like the kind of subtle algorithm that if you taught it to most undergrads, they would be lost.
19:04 <monochrom> In other words a very subtle algorithm, if it's correct afterall, requires a non-obvious proof of course.
19:04 <erisco> does it partition on <, =, and > ?
19:04 mgalese joined
19:05 <cocreature> I don’t remember :)
19:05 wraithm joined
19:05 pera_ joined
19:05 mettekou joined
19:05 <erisco> I get why it exists, but it is funny to have this for Java
19:05 <erisco> retrofitting to the extreme
19:06 mikecaruso joined
19:06 <cocreature> monochrom: it’s even worse when you’re talking about parallel quick sort. one of the parallel versions uses one pivot per processor
19:06 <nomeata> Hi. I could need a little help playing around with dependent type ideas in Haskell. I have a “type level state machine” consisting of 'data Tag = A | B', 'data Family Action :: Tag -> *' and 'type family Next :: Action t -> Tag'. Now I have a 'data familiy State :: Tag -> *', and I want to implement a function 'transition :: Event -> State s -> (a :: Action, State (Next a))', but such dependent products do not exist in Haskell yet. How owuld I encode that?
19:06 uncertainty joined
19:06 the|auriscope joined
19:07 binu joined
19:07 <monochrom> Did you know: Spec# is "from the makers of ESC/Java", and the transition is really the transition from "working at Digital/Compaq" to "working at Microsoft"? :) (Also, it was ESC/Modula before ESC/Java.)
19:07 Luke joined
19:08 <erisco> nomeata, can you briefly describe what roles Action, Next, and State play?
19:08 thunderrd joined
19:08 mettekou_ joined
19:08 jle` joined
19:08 jle` joined
19:09 <monochrom> ESC/Java is now unmaintained therefore. But another Java model, more recent and alive, is in ACL2.
19:09 <cocreature> monochrom: spec# is also dead
19:09 <erisco> if your state machine were a graph, what is each of these? I presume State is a labeled vertex
19:09 Ayey_ joined
19:09 mson joined
19:09 <monochrom> Darn. It was so good while it lasted.
19:10 infinity0 joined
19:11 oisdk joined
19:12 electrocat joined
19:12 allenj12 joined
19:12 <nomeata> erisco: `data instance Action A = StayInA | GoToB`, for example, with `type instance Next GoToB = B`
19:13 <nomeata> erisco: and `State` would capture the actual state of a state machine (e.g. state of the UI elements)
19:13 <erisco> okay, so, Action are edge labels
19:13 <reactormonk> How would you flip type arguments?
19:13 <lpaste_> allenj12 pasted “haskell error messages?” at http://lpaste.net/353570
19:13 <nomeata> Via another channel I learned that I will probably not get around defining singletons for the `Action` constructors.
19:13 <erisco> type Flip f a b = f b a
19:13 <reactormonk> similar to the value-level flip.
19:14 <erisco> but if you want to partially apply you need newtype Flip f a b = Flip (f b a)
19:14 <geekosaur> allenj12, it means you are trying to add or subtract from something whose type is (Int, Int) and there is no standard Num instance for that type
19:14 raichoo joined
19:14 nycs joined
19:14 the|auriscope joined
19:14 troydm joined
19:14 <tfc> hey there, i am currently running a "forever-running" shell command in my haskell app with createProcess. then read some output with hGetLine for some lines until i stop being interested in its output and then use terminateProcess to get rid of it again. i realize that terminateProcess is maybe not the right thing becasue i would normally kill it with STRG+C as a normal shell user. any alternative?
19:15 <geekosaur> (Haskell's numeric hierarchy is extensible, and there are actual uses for that type in some situations; but not commonly enough that the standard libs support it)
19:15 connrs joined
19:15 mekeor joined
19:15 <geekosaur> tfc, terminateProcess is actually the correct thing for noninteractive use like that
19:15 <geekosaur> (n particular, on Windows)
19:15 caumeslasal joined
19:15 chrisdotcode joined
19:16 Ayey_ joined
19:16 <tfc> geekosaur: even if it is a network application? i am worrying that it might be dangerous
19:17 <erisco> nomeata, how about a type family S' :: State s -> Action a -> State s ?
19:17 <monochrom> Normal shell user uses SIGINT because users are lazy and the shell makes SIGINT easy but SIGTERM difficult.
19:17 <geekosaur> tfc, *something* is running locally. and if it's not handling SIGTERM properly then you're probably screwed anyway
19:17 <geekosaur> like someone ctrl-alt-del at the wrong time could corrupt the remote --- this is BAD
19:18 <erisco> or something like that
19:18 <geekosaur> (among other things that will send all processes SIGTERM, wait a bit, then SIGKILL anything that didn't go away by itself)
19:18 <tfc> i see. so if that app i am executing is handling terminateProcess correctly, then i do not have to worry?
19:18 <erisco> it is tough for me to get a picture of what you're trying to do
19:18 <geekosaur> yes
19:18 <Tuplanolla> You probably want to use both `Control.Exception` and `System.Posix.Signals`, tfc.
19:18 <tfc> ok, thank you
19:18 <geekosaur> Tuplanolla, only if they control the program being run; they;re bnot helpful in the one doing the running
19:19 mgalese left
19:19 <monochrom> Yeah we're talking about the parent process.
19:19 <allenj12> geekosour: interesting, im looking at it more but I cant find any instance, I only found an error in the Then statement. how come it dosnt list a specific location?
19:19 mgalese joined
19:20 rbnnn joined
19:21 <nomeata> erisco: Yes, I guess I should get myself clearer what I am trying to do :-)
19:21 <Tuplanolla> Oh, well, there's not much the parent can do.
19:21 <geekosaur> allenj12, it "did", it told you exactly what is triggering it
19:21 <geekosaur> not by line/column but by the text of the expression
19:21 <erisco> nomeata, there are many ways to have a state machine, is the problem
19:21 <rbnnn> Hello. I have recently become interested in functional programming. Can anyone give me a resource that tells me why copying thins all the time isn't super slow? It defies how I think about things so I guess I'll learn something
19:22 <geekosaur> (go 0 []) is producing something that is being used as a Num instance ("a number") --- but its actual type is (Int,Int)
19:22 augur joined
19:22 <geekosaur> this is not automatically illegal because there are cases when you *wnt* that to have a Num instance. this just isn't one of them
19:22 <barrucadu> rbnnn: Copying things all the time is super slow! However, when all data is immutable, the compiler can often avoid copying.
19:23 <erisco> nomeata, generally speaking you can use singletons to emulate the dependent pair
19:23 <barrucadu> For example, prepending an item to a list doesn't necessitate copying the tail.
19:23 <nomeata> erisco: thanks, I will dig deepter in that direction.
19:23 <rbnnn> barrucadu: I sorta get it... Compiler can defer reading/copying because the source object does not change.. Do you have any reading?
19:23 <erisco> nomeata, so this will look like (Sing (Action a), State (Next a))
19:24 <barrucadu> rbnnn: Not really, and unfortunately I have to go out now. But perhaps someone else will.
19:24 mgalese left
19:24 <rbnnn> alright, have a good day/night wherever you are
19:24 <monochrom> allenj12: What does l++[0] mean? where l = [(1,1), (2,3), (3,1)] for example. So, what does [(1,1), (2,3), (3,1)] ++ [0] mean?
19:24 <geekosaur> allenj12, specifically when the recursion bottoms out you are producing a tuple (line 26 in your paste).
19:24 <erisco> nomeata, or something like that, not sure how all your pieces work
19:25 <allenj12> monochrom: I messed up in a couple spots that didnt change the error let me update it
19:25 chrisdotcode joined
19:25 <lpaste_> allenj12 revised “haskell error messages?”: “haskell error messages?” at http://lpaste.net/353570
19:25 <monochrom> OK, then this should have an error.
19:26 UserJosh joined
19:26 <monochrom> err, this shouldn't have an error.
19:26 harrison joined
19:27 twanvl joined
19:27 <allenj12> monochrom: still is :(
19:27 <geekosaur> result is a list of tuples, it gets produced when recursion bottoms out, the expected type should be [Int] per the signature of mul, not [(Int,Int)]
19:27 takle joined
19:27 jle` joined
19:27 <monochrom> No, I just tried on my ghci. No error.
19:27 <geekosaur> but I don't see how this triggers a Num instance issue instead of a simple type mismatch
19:28 coltfred joined
19:28 <geekosaur> oh wait, I'm conflating two `result`s, whoops
19:28 <allenj12> im using a ghci instance in emacs, let me restart it
19:28 <allenj12> geekosaur: my naming is horrible, my fault
19:28 <allenj12> :D
19:28 Philipp joined
19:28 <monochrom> Yeah I abstracted away from the detailed code of step.
19:29 <Cale> allenj12: In any case, that error generally means that you used an (Int, Int) pair as if it were a number.
19:29 <allenj12> monochrom: it works now, looks like i just needed to restart my instance
19:29 <Philipp> Hey guys. Just started to learn haskell after many years on imperative languages and I think it is awesome :D
19:29 doodlehaus joined
19:29 <Cale> also, it's customary to line up the 'then' and 'else'
19:29 <allenj12> Cale: yea which was right, was just really hard to pin down for me. I will get use to it with time. Also thanks for the style tip
19:30 <Cale> Philipp: Nice! Feel free to ask any questions you might have.
19:30 doodlehaus joined
19:30 <Philipp> Yeah, I think, I will. Thanks!
19:30 mgalese joined
19:30 electrocat left
19:30 <monochrom> In this case it was using 0 as if it were a tuple.
19:31 simendsjo joined
19:31 <Philipp> But i'm still searching where I can apply haskell
19:31 bodisiw joined
19:31 <Rembane> EVERYWHERE!
19:31 <Cale> Philipp: I use it for almost everything
19:31 systemfault joined
19:32 <Cale> Philipp: At the place where I work, we build web applications for various clients, and write both the frontend and backend in Haskell
19:32 <Philipp> I love Lua and ++ too, I think, they will be offended at me
19:32 <Rembane> Cale: Do you use ghcjs to turn Haskell into Javascript?
19:32 <Cale> yep
19:32 <Rembane> Cool.
19:32 <Cale> and we use Reflex-DOM
19:32 Levex joined
19:32 <Cale> which is amazing :)
19:32 <Rembane> :D
19:32 <Philipp> So, am I right, that Haskell can do almost everything?
19:33 <Rembane> Philipp: it isn't very good at embedded programming, but not much is
19:33 <monochrom> You can use Haskell wherever you are proficient enough with Haskell. Which means almost nowhere for now but almost everywhere in the future when you get good.
19:33 <monochrom> But that's tautological because it's true of every language.
19:33 <Philipp> Is there any games on haskell?
19:34 <Cale> There are a few.
19:34 jud^ joined
19:34 <monochrom> Even when you heard "C is widely used in system programming", you could still not do it yourself when you were a beginner.
19:34 <Philipp> Yeah, I understand this
19:34 <grayhatter> monochrom: I disagree
19:34 <kadoban> Not many games, a couple? It's maybe not the best choice if your goal is like FPS games, just because not many have gone before you.
19:34 <Philipp> Right now I am on the first chapters of learnyouahaskell, so I can't fully understand whole power
19:35 <grayhatter> I could write a game much faster in java, than in haskell
19:35 <grayhatter> I would say EVEN faster in python, but I already know much more python
19:35 yogsototh left
19:35 <Cale> I actually believe that Haskell will eventually be an amazing language in which to write games
19:35 <Cale> It's just that the pieces have not all come together quite yet.
19:35 <grayhatter> like any tool, it's the job of the person holding it to use it correctly
19:35 <bodisiw> Philipp, i have been at it a few months, and i just looked back over the cheat sheet i tried to use as a shortcut initially... and now i understood most of it!
19:35 <grayhatter> I could build a house with just a machette
19:36 <grayhatter> but it'd be faster to use a table saw+hammer
19:36 <MarcelineVQ> Cale: compact regions being a major piece in that direction, if I understand them anyway
19:36 <Philipp> No, I'm not going to make games on haskell. But I'm really interested in some random-generation with it
19:36 <Philipp> Mazes/dungeons/etc
19:36 <Philipp> I think it should be very good at it
19:36 <grayhatter> Philipp: lol, haskell doesn't do random
19:37 mstruebing joined
19:37 <grayhatter> err
19:37 <Philipp> Ok, then I will find some new purposes :D
19:37 <Cale> MarcelineVQ: I dunno -- I don't see GC as a huge obstacle actually.
19:37 <grayhatter> rather: haskell doesn't do IO
19:37 <Cale> MarcelineVQ: Of course, it depends on how much allocation pressure your game is going to have!
19:38 <monochrom> No, I use Haskell for both random and IO all the time. https://github.com/treblacy/random-read
19:38 <Cale> grayhatter: Haskell does IO
19:38 <Philipp> monochrom: Who should I believe?
19:38 <monochrom> I have actual code right there. Do not believe people. Believe actual code.
19:38 <grayhatter> if I write a haskell libaray, and then use that libarary in C or python or [other], won't it's lazyness lose it's benifit?
19:39 <Tuplanolla> I don't see Haskell ever making it into hpc, but anything else should be within its reach.
19:39 <Cale> Philipp: I'm paid to write web applications entirely in Haskell. If Haskell didn't manage I/O well, my job would be pretty silly.
19:39 <kadoban> grayhatter: "haskell doesn't do IO" ... what?
19:39 <grayhatter> can haskell even return ([1..]::Int)
19:39 <Philipp> By the way, is haskell could be used with some other languages? Or it is only standalone?
19:40 <bodisiw> could there be a distributed thunk haskell Tuplanolla?
19:40 <kadoban> Philipp: It has FFI to C and with GHCJS to JavaScript. Other languages can be reached through C, most languages have a C FFI.
19:40 <Philipp> Probably, I don't need anything except C
19:40 <shapr> grayhatter: are you learning Haskell?
19:40 <grayhatter> kadoban: Cale monochrom I was making a subtle joke that Haskell was written with other goals in mind. Haskell can do IO just fine, but saying haskell does IO is like saying python does speed
19:41 <Cale> grayhatter: GHC's IO manager is excellent
19:41 <shapr> grayhatter: Would high throughput Haskell apps be a good counter-example?
19:41 <Cale> It has an n:m thread scheduler which is very fast
19:41 <grayhatter> Cale: GHC != Haskell
19:41 <grayhatter> *arguably
19:41 <kadoban> grayhatter: It's both not and "python does speed" isn't nonsensical either. Haskell is a perfectly fine imperative language, including doing IO operations.
19:41 <Cale> GHC is what everyone programming in Haskell seriously uses.
19:41 <Cale> GHC and GHCJS
19:42 <Cale> grayhatter: http://haskell.cs.yale.edu/wp-content/uploads/2013/08/hask035-voellmy.pdf -- check this out
19:42 <Philipp> Oh, by the way, is "learnyouahaskell" good enough?
19:42 <Philipp> Or can you advice something better?
19:43 <grayhatter> Cale: sure, but my assertion wasn't that GHC makes haskell, more like; because the compiler compiles something nicely, doesn't mean it's best use
19:43 <kadoban> grayhatter: Haskell isn't cool because IO/imperative is hard, it's cool because the type system can understand the difference between imperative code and pure code.
19:43 <shapr> Philipp: I like haskellbook.com best right now
19:43 <shapr> Philipp: it does cost $60, but it also comprehensive with many excellent homework exercises
19:43 <shapr> Philipp: if you want free, there's cis194
19:43 marcopullo joined
19:43 <shapr> @where cis194
19:43 <lambdabot> http://www.seas.upenn.edu/~cis194/spring13/
19:43 <kadoban> Philipp: LYAH is pretty not good on its own. I'd do haskellbook.com (not free), or cis194 spring '13 along with LYAH. The former greatly preferred.
19:44 caumeslasal joined
19:44 psychicist__ joined
19:44 <grayhatter> kadoban: sure, but until you learn a style that NO other language uses haskell is a broken style
19:44 <shapr> grayhatter: wait what?
19:44 <Cale> grayhatter: Well, if you're talking about how good Haskell is at expressing I/O, I'll still disagree with you -- Haskell is my favourite imperative language by far, and there are also non-imperative ways to handle I/O as well. In fact, I spend a lot of my time at work using Reflex-DOM, which is a library built atop Reflex, a functional reactive programming library.
19:45 <kadoban> Not really following what you're saying there, grayhatter
19:45 <grayhatter> learn how to drive an automatic car, and then learn a stick. while both have advantages, one seems broken until you learn how to use it
19:45 <Philipp> I mean, is it good enough to just feel the language?
19:45 <shapr> oh, I see ... you're saying that the Haskell style is unique and thus appears nonsensical from the outside?
19:45 <Cale> It lets me declaratively express what the DOM ought to be and the interactions between the things which affect it.
19:45 <shapr> grayhatter: that sounds like support for Paul Graham's blub paradox
19:45 <grayhatter> shapr: that's much closer to what I meant
19:45 <Cale> and takes care of all the I/O involved in that
19:46 Destol joined
19:46 <kadoban> Philipp: LYAH? It's good enough to maybe kinda sorta give you a taste. Just don't expect to come out the other end actually able to write much/any haskell code, unless you do much more beyond LYAH than just read it.
19:46 <grayhatter> shapr: the problem with haskell (other than no one really understands monads) is people who use it are all too smart
19:46 <Philipp> Yeah, I understand
19:46 <shapr> grayhatter: I agree, my coworkers find it difficult to understand why a Functor instance for everything is so powerful.
19:46 <Philipp> My problem is that haskell is my first functional language
19:47 <Cale> So, we build web applications and our default is to have everything live updating, because the FRP library makes that easy -- you almost have to go slightly out of your way to freeze things :)
19:47 <grayhatter> #haskell is a GREAT example of this
19:47 <shapr> grayhatter: I got a job writing Haskell before I'd ever taken a college course in math or CS
19:47 <shapr> grayhatter: so I have anecdata that disagrees.
19:47 <* geekosaur> has zero degrees
19:47 <kadoban> grayhatter: Monad is way overblown.
19:47 <shapr> grayhatter: in my opinion, people believe that Haskell is scary, and that's the real problem
19:47 <davean> shapr: can we use you as an exemplar of anything never?
19:47 <Cale> grayhatter: I understand monads. There's really not a whole lot which needs understanding about them to use Haskell (and I understand a fair amount more than that)
19:47 <grayhatter> I'll ask a question and get a GREAT technical example that makes NO sense
19:47 <shapr> grayhatter: I just got a degree three years ago! after fifteen years of a career
19:47 <grayhatter> until I understand everything about it
19:47 <shapr> davean: that's a fair point
19:48 <grayhatter> shapr: no
19:48 <geekosaur> also tryinbg to approach Monad from the math view is entirely incorrect. Haskell Monad *is not* the CT construct; it's merely inspired by it, and for almost all purposes you don't care
19:48 <Cale> grayhatter: I mean, you can't expect to understand everything all at once of course :)
19:48 <grayhatter> here
19:48 <shapr> grayhatter: no what?
19:48 <grayhatter> let me find the page that made me NOT hate haskell
19:48 <Cale> geekosaur: Well, that's a little unfair
19:48 <monochrom> "the right tool for the right job" taken to an exclusive extreme (like languages are mutually disjoint) is also another real problem.
19:48 alx741 joined
19:48 <Cale> geekosaur: It really is the CT construct -- it's an example of it anyway
19:48 Ayey_ joined
19:48 <bodisiw> Philipp, if you like video, i really found the 'Modeling Data in Haskell for Beginners' talk on youtube helpful... by the same guy as wrote haskellbook.com
19:48 Glooomy joined
19:49 Luke joined
19:49 <Cale> geekosaur: But you don't need to understand that in full generality just to use it in Haskell
19:49 <Philipp> Is it a bad that I found haskellbook for free?
19:49 <Cale> heh, ask bitemyapp
19:49 <monochrom> My random-read program could be written in C, Perl, or Haskell equally fine.
19:49 jsgrant- joined
19:49 <shapr> Philipp: I met one of the authors recently, she's writing another book. In my opinion, if you get benefit from the book, buy a copy!
19:50 <grayhatter> https://wiki.haskell.org/Haskell_IO_for_Imperative_Programmers
19:50 <grayhatter> I've been "writing" haskell for weeks before I read this
19:50 <Philipp> Yeah, I agree with that. But I still not sure, if I will get any benifit from that book
19:50 <grayhatter> and I hated every bit of it
19:50 <kadoban> Philipp: The author(s) might think so. It probably depends on your morality construct I guess (don't even mean that in a judgemental way). If you have the money though and get something out of it, maybe try to buy a copy if feasible. The authors are pretty cool and helpful and put a lot of work into that book.
19:50 <shapr> grayhatter: but now you're in love with Haskell?
19:50 connrs joined
19:51 <grayhatter> The problem is imperative-think... the virtues of laziness.
19:51 <grayhatter> no
19:51 <grayhatter> I still hate it
19:51 <grayhatter> but at least I like working with it now
19:51 <shapr> ah, so why participate here?
19:51 <Cale> grayhatter: It took me a couple of months to feel like I could do anything useful with Haskell and about a year to be "comfortable" for some definition of the word
19:51 <grayhatter> shapr: because it's hard
19:51 <Philipp> kadoban: I would be happy to buy copy, but I don't have any money for now
19:51 <grayhatter> and I don't understand it
19:51 <shapr> hate is hard? I'm confused.
19:51 <shapr> oh, Haskell is hard?
19:52 <grayhatter> right
19:52 <monochrom> I recommend not thinking in terms of "love", "hate", "broken".
19:52 <Cale> grayhatter: and I started out knowing at least a dozen programming languages fairly well (though a shortage of functional ones among them)
19:52 <shapr> grayhatter: You have a surprising amount of global state in your sentences :-P
19:52 ubsan_ joined
19:52 <grayhatter> lol, sorry
19:52 <monochrom> For example I wouldn't say "C is broken" even though I align with Haskell's way.
19:52 <grayhatter> I'm also home sick, so I'm likely a lot less sensical than I think I am
19:52 <Cale> Now I've probably used more than twice that number a fair amount, and a wider variety among them, and Haskell is still what I reach for in most practical tasks.
19:52 <Philipp> Anyway, thanks for help
19:53 <davean> monochrom: being broken suggests something is defined enough to be wrong!
19:53 <shapr> Philipp: come on down and ask more questions next time!
19:53 <grayhatter> monochrom: you're right, nothing is really broken.
19:53 allenj12` joined
19:53 <Philipp> Yeah, I will!
19:53 <Cale> davean: :D
19:53 <kadoban> Philipp: Good luck in your learning, definitely come back when you run into trouble, or regardless :)
19:53 <Philipp> Good night everybody
19:53 <grayhatter> I meant more a position as opinion, not as backed up by reason
19:53 <Cale> Good night!
19:53 <davean> monochrom: I think C is a wonderful assembly tempalte language
19:54 <Cale> grayhatter: But I highly encourage you to sit around here and absorb things by osmosis and ask questions whenever you hit something that you're struggling with
19:54 <shapr> grayhatter: I concur
19:54 <grayhatter> Cale: I often do
19:54 <Cale> It doesn't stay frustrating forever :)
19:54 <grayhatter> no, it's not too fustrating anymore
19:54 <shapr> On the downside, all the other languages suddenly get frustrating :-(
19:54 <grayhatter> no more than any other language at this point
19:55 <grayhatter> once I finally understand haskells assoiative syntax, I'll stop hating it
19:55 sidei joined
19:55 <shapr> that sounds like a positive change
19:56 <grayhatter> and/or someone fixes the syntax highlighter in sublime text
19:57 ramzifu joined
19:57 <reactormonk> grayhatter, emacs works nicely >:)
19:57 <kadoban> sublime's haskell hilighter is crap? That's unfortunate
19:57 <shapr> grayhatter: is it something you could improve?
19:57 <grayhatter> reactormonk: I'm sure it does
19:57 <shapr> I don't use sublime, sadly.
19:57 <grayhatter> I don't have the spare time to learn and setup a new editor
19:58 <reactormonk> grayhatter, ... the >:) is an evil smile, the closest thing I can do to a trollface.
19:58 <grayhatter> shapr: I probaly could, but I wouldn't even try... I don't know enough haskell yet
19:58 <Cale> Our team is insanely productive. We took an app that we'd been working on for one client for about a year, and just one other team member and I sat down and made it multi-tenant in about 3 days -- i.e. we converted the backend such that it effectively served multiple copies of the web application, each with their own database schema. This is something which often would require weeks, or starting from scratch, but the type system is
19:58 <Cale> just really really good at helping refactor stuff. We changed out the type of our authentication tokens, and a type which represented a pool of database connections, and the resulting type errors basically took us through all the changes which needed to be made throughout our backend.
19:58 <grayhatter> reactormonk: yeah, I got the intent before, the dry response was intentional so I wouldn't meme respond
19:59 Xerus joined
19:59 <reactormonk> grayhatter, but then there was the second one, which had a bit more juice. :-P
19:59 <grayhatter> I'd already started typing out an argument for vim, but decided not to start that discussion this time
19:59 <shapr> I'm beginning to feel like I should push for a Haskell-specific editor, like IDLE is for Python
20:00 <Cale> The app is a chat service somewhat like Slack, but with additional features like email integration with the chat, surveys, and a bunch of other organisational features.
20:00 <grayhatter> shapr: yes pls
20:00 Ayey_ joined
20:00 <reactormonk> shapr, or atom for JS?
20:00 <shapr> As in, start a kickstarter or something... send money to one of the Haskell consultancies.
20:00 <shapr> reactormonk: yup, that kind of thing.
20:00 <grayhatter> shapr: you have NO idea how much that would help me in trying to fix segments of errors
20:00 <bodisiw> Cale, does the type system help with things like schema changes in the database?
20:00 mizu_no_oto_work joined
20:01 <grayhatter> shapr: model the spec after something like learnyouahaskell
20:01 <shapr> the editor spec?
20:01 <shapr> je suis confuse
20:01 <kadoban> shapr: I can only imagine that money would be better spent improving integration in existing editors, something like that hie thing that got started and didn't seem to go too far maybe.
20:01 <grayhatter> shapr: right
20:01 serendependy joined
20:01 <Tuplanolla> User manual driven programming, shapr.
20:01 <kadoban> Not that I'm the decider of where anyone's money goes of course.
20:02 <grayhatter> a haskell IDLE should be able to have a history that you can reference
20:02 <shapr> Tuplanolla: en ymmaerrae
20:02 <joeyh> is there any way to hide instances from default display in haddock?
20:02 <grayhatter> ghci as an editor
20:02 <Tuplanolla> You write the user manual first and use that experience to guide your design, shapr.
20:02 <Cale> bodisiw: Well, we sort of coerced it to. I took the function which runs a database transaction given a pool of connections, and generalised it so that instead of just a plain pool of connections, it could take what amounted to a pair of the schema to use and that pool instead (and we defined a WithSchema functor which paired on the schema name)
20:03 <Tuplanolla> Defects come up before you have a single line of code.
20:03 <shapr> Tuplanolla: I can't tell if you're being sarcastic or not, but I hope yes?
20:03 <shapr> Tuplanolla: have you done something like that?
20:03 <joeyh> hmm, I suppose I could move the instances to a newtype or something
20:03 <Tuplanolla> Yes, twice already, shapr.
20:03 <Cale> bodisiw: This WithSchema functor also wrapped the unencrypted contents of our auth tokens
20:03 <grayhatter> shapr: iphy did something like that for hstoxcore
20:03 <grayhatter> the spec is inline, so when you start writing code, how everything works is already there
20:04 <Cale> bodisiw: and having made those changes, the compiler started complaining at us a bunch about all the things we needed to consider.
20:04 <grayhatter> If I understand correctly
20:04 <shapr> Tuplanolla: is that written up / described somewhere? And hopefully in something other than Finnish?
20:04 <davean> shapr: I've never actually seen IDLE used
20:04 <shapr> My finnish is pitiful
20:04 jud joined
20:05 <shapr> davean: I used to use it a bunch to teach Python, but pycharm is better now.
20:05 <Tuplanolla> No, shapr. It's just a guiding principle. If you can't explain your idea clearly, it's a bad idea or you don't understand it. Either way it's better to give up early.
20:06 Xerus left
20:06 augur joined
20:06 <Cale> bodisiw: and basically by the time we were done, we had a working multi-tenant app -- of course with a few details here and there where it wasn't totally straightforward, like dealing with separate subdomains and such in various places -- but the compiler was amazingly helpful at keeping the pair of us on track and busy and not having to stumble around and wonder about what stuff would be broken and need fixing
20:06 nomotif joined
20:07 <shapr> Tuplanolla: that's an interesting idea
20:07 sellout- joined
20:07 ZelteHonor joined
20:07 fProgrammer joined
20:08 <bodisiw> Cale, i'll take all the help i can get :-) i imagine service boundaries are inescapable, but what you described still sounds awesome
20:08 dachary1 joined
20:08 LeCamarade joined
20:10 Ayey_ joined
20:10 psychicist__ joined
20:11 <ZelteHonor> Am I the only one who's hype by linear type?
20:11 <fProgrammer> quick question: I'm fairly new to developing webservices using Scotty framework, I can't find any documentation on how to deploy scotty app. Currently I deploy it by "stack exec projectName", How do we deploy it using Apache/Nginx anyone?
20:12 <Cale> fProgrammer: I don't know why you would use Apache...
20:12 <Cale> When you write a web app using Scotty, your app *is* the webserver
20:12 <Cale> You may still want to put a load balancer in front of it
20:13 <bodisiw> ZelteHonor, i am... but i need to learn linear logic better, so its premature for me... also its dismaying if i have to type unicode characters
20:13 <bodisiw> i hope to use -o
20:13 <Cale> I wasn't the one to do that setup for our apps, so I couldn't tell you too much about how to configure nginx
20:13 <ZelteHonor> I don't think learning linear logic is a prerequisite.
20:13 <fProgrammer> Cale: Got it! Am I deploying it correctly though? stack exec project-name?
20:14 <geekosaur> ?
20:14 <geekosaur> stack exec does not deploy, it runs something that may or may not be deployed
20:14 <ZelteHonor> -o
20:14 <Guest____> Anyone here familiar with ghc-mod and neco-ghc's internals?
20:14 <ZelteHonor> I am curious how it will interact with the existing ecosystem.
20:15 <bodisiw> okay then... i still need to learn haskell :-)
20:15 <ZelteHonor> I've read the blog post, but not the paper.
20:15 <fProgrammer> geekosaur: okay understood.
20:16 <dylukes> fProgrammer my suggestion is that you build your scotty app, and then put it behind nginx as a reverse-proxy/load-balancer.
20:16 <bodisiw> paper reads pretty easy, from what i started... mostly about where the memory gets allocated, seems like
20:16 <Cale> fProgrammer: I don't think stack does too much when it comes to actually setting up a remote machine environment the way you want. It'll build your project for you, but deployment is still largely up to you.
20:16 Xerus joined
20:17 <Cale> fProgrammer: We use nix where I work, and it's a lot more comprehensive in that regard (though I personally dread working on nix configuration, it's nice when you have someone who knows it well to set things up)
20:17 cdg joined
20:18 <dylukes> fProgrammer you can either use Scotty as the webserver and use server entries in an upstream block, or you can use wai-handler-fastcgi (has that been superceded?)
20:18 <Cale> dylukes: Oh, I forgot about that
20:18 <dylukes> In general, it's been my experience that putting nginx in front of anything web facing is a good idea.
20:18 <dylukes> Using built in webservers is often more convenient in the short term but less convenient in the long term.
20:18 <Cale> But yeah, you shouldn't need it just to use nginx
20:19 oisdk joined
20:19 <dylukes> http { upstream myapp { server foo.bar.whatever; }
20:19 <dylukes> server { listen 80; location / { proxy_pass http://myapp } }
20:19 <fProgrammer> dylukes: Usually built-in webservers are for development, which prompted me to enquire more about scotty
20:19 <dylukes> If you add multiple servers to the upstream, nginx will load balance.
20:20 <fProgrammer> dylukes: yes!
20:20 <dylukes> Scotty uses Warp, which is WAI.
20:20 <dylukes> nginx, Apache, etc use CGI.
20:20 <dylukes> There should be separation of concerns though.
20:20 <dylukes> Generally I handle load balancing, proxying, TLS, etc in nginx and keep that out of the application itself.
20:20 locallycompact joined
20:21 <dylukes> http://nginx.org/en/docs/http/load_balancing.html
20:21 <dylukes> Also, if you're deploying in a containerized environment, you can write a quick script to pull the endpoints from each container and generate the nginx config.
20:22 ubsan_ joined
20:22 <dylukes> Pretty much all of my personal projects as well as contracts are nginx + containers.
20:22 <dylukes> You can use this: https://github.com/jwilder/docker-gen
20:23 <dylukes> (or higher level: https://github.com/jwilder/nginx-proxy)
20:24 subttle joined
20:25 <dylukes> Cale: also hey Cale!
20:25 <dylukes> It's been a while :).
20:25 <fProgrammer> dylukes: So help me understand this, I've a scotty web app hosted on github/bitbucket, I pull the changes on remote machine/container, build it and execute the binary? Sorry I come from "war" lineage where we build a war file which is copied from a CI etc
20:25 <mauke> I thought nginx didn't support CGI
20:25 <Cale> hey :D
20:25 <dylukes> mauke It supports fastcgi.
20:25 <mauke> ok, that's a bit different :-)
20:26 <Cale> fProgrammer: yeah, assuming that the application is reasonably self-contained, that sounds about right. You might want to script that process.
20:26 <fProgrammer> Cale: got it! Thanks for the help!
20:26 <dylukes> I don't know if there's a stack buildpack, but,
20:26 <dylukes> I rather like dokku for small deployments.
20:27 <dylukes> It's very handy.
20:27 <dylukes> But it's worth doing it manually first to learn how the ecosystem works.
20:27 <dylukes> fProgrammer WAR/EARs work because they're self contained and target a virtual machine (JVM).
20:27 <Cale> fProgrammer: Where I work, we have a script which does a nix-build of a complete system configuration for an AWS machine, and then uses nix-copy-closure to send it, and then ssh'es in and switches to the new configuration
20:27 <dylukes> the idea with containers is similar, but you're packing an entire system, not just filesystem.
20:27 <shiona> I have a python program that uses subprocess.Popen to run a program, pipes stdout and stdin into its own use and expects one line in input (from the subprocess) after which it would send a crapton of stuff to the subprocess. I'm giving it a haskell program and 'putStrLn "test"' terminates, but 'putStrLn "test" >> getLine' does not.
20:28 <dylukes> Cale that's very... yo.
20:28 <dylukes> you*
20:28 <shiona> I assume I'm either too drunk to code, or there's something I don't understand about how lazyness works in this case
20:28 <dylukes> I need to learn Nix.
20:28 <fProgrammer> dylukes: Makes sense, thanks!
20:28 <glguy> shiona: Nothing to do with laziness, probably something to do with buffering
20:28 <dylukes> fProgrammer just remember that docker is a finicky piece of crap.
20:28 <dylukes> It generally works great as long as you don't poke it too hard or need to mess with cgroups or anything.
20:28 <shiona> ah
20:29 <dylukes> At that point... may god have mercy on your soul.
20:29 <Cale> dylukes: So do I actually -- I've just been living well by being surrounded by people who know how to use it better than I do
20:29 <glguy> shiona: You can either set the buffering mode in your Haskell program to NoBuffering or LineBuffering, or you can explicitly hFlush stdout
20:29 Xerus left
20:29 <shiona> thanks. Forgot that stuff
20:29 <dylukes> Cale I'm jealous :(.
20:29 <dylukes> I'm in academia writing python scripts all day currently.
20:29 structuralist joined
20:29 <mauke> avoid NoBuffering like the plague
20:29 fotonzade joined
20:30 <mauke> unless you like seeing write(..., 1) calls everywhere in your strace output
20:30 <shiona> in this case LineBuffering works fine
20:30 <dylukes> strace is another program I need to learn.
20:30 <dylukes> Or, dtruss on OS X.
20:30 <mauke> the basics are easy. 'strace yourprogram --options' :-)
20:31 kuribas joined
20:31 Habib_ joined
20:31 faberbrain joined
20:33 replay joined
20:33 <grayhatter> is there anything overtly wrong with this https://gist.github.com/36c4c48f4a2977a1568722a1b215afed
20:33 <Habib_> Does anyone know a function that can generalise IsString values to the typeclass?
20:33 <dylukes> Hrm. Still can't get man pages opening in vim nicely.
20:33 <dylukes> So many ^Hs...
20:34 oisdk_ joined
20:34 <Habib_> For example, say I have a function f, which calls another function g with the type ByteString -> ByteString
20:34 <Habib_> I can turn f into a generalised g with the type IsString stringy => ByteString -> stringy
20:35 <Habib_> But I can't turn it into a function with the type IsString stringy => stringy -> stringy
20:35 <Habib_> Can I?
20:35 ajhager joined
20:35 <Habib_> grayhatter, I would use the maybe function
20:35 <Habib_> Sorry, the fromMaybe function
20:36 <mauke> grayhatter: it looks like it's repeating a lot of work
20:36 <Habib_> Actually, maybe looks good for this instance
20:36 ubsan_ joined
20:36 boccato joined
20:36 <mauke> :t partition
20:36 <Habib_> No, wait.
20:36 <lambdabot> (a -> Bool) -> [a] -> ([a], [a])
20:36 <glguy> Habib_: If you look at the definition of the IsString class you'll see that it only provides for fromString :: IsString a => String -> a
20:37 ajhager joined
20:37 <glguy> So that class isn't going to help you to write toString :: IsString a => a -> String
20:37 raichoo joined
20:37 <Habib_> glguy, yeah, I was hoping that was because Haskell gives you toString for free from fromString or something like that.
20:38 curious_corn joined
20:38 <grayhatter> Habib_: I can't
20:38 jsgrant- joined
20:38 <Habib_> Well, it's probably more like toString :: IsString a => a -> a, because I want to be able to pass any IsString instance and use it as an arbitrary IsString instance.
20:38 <grayhatter> there's no promise that channel will exist
20:39 <grayhatter> wait
20:39 petervaro joined
20:39 <mauke> :t \search -> first listToMaybe . partition (\x -> ?chname x == search)
20:39 <lambdabot> (?chname::t -> a, Eq a) => a -> [t] -> (Maybe t, [t])
20:40 <grayhatter> huh
20:40 curious_corn joined
20:41 <Habib_> grayhatter, maybe (Nothing, cs) (flip (,) other) found?
20:41 <Habib_> maybe (Nothing, cs) (flip (,) $ other) found
20:41 <mauke> Habib_: that can be simplified to (found, other)
20:41 monochrom joined
20:42 <Habib_> The maybe there is a function call.
20:42 <Habib_> But it doesn't typecheck.
20:42 <Habib_> Because the left tuple is a (Maybe a, b)
20:42 <Habib_> and the right is an (a, b)
20:42 <jle`> case partition (\x -> search == cname x) cs of
20:43 solatis joined
20:43 <jle`> (x:xs, ys) -> (Just x, xs ++ ys)
20:43 <jle`> ([], ys) -> (Nothing, ys)
20:43 sdothum joined
20:43 <mauke> jle`: that's semantically different
20:43 <mauke> the original code doesn't return xs
20:43 louispan joined
20:43 <jle`> oh i see
20:44 wraithm joined
20:44 <Habib_> if isJust found, isn't cs == other?
20:44 <jle`> then (x:xs, ys) -> (Just x, ys)
20:44 <Habib_> In that case, why not just say (found, other)
20:44 <mauke> jle`: that's equivalent to my version :-)
20:44 <Habib_> Just read the whole thing properly.
20:44 <Habib_> I think.
20:44 <jle`> my intent was to be identical to your version, just more pointful :3
20:44 Ayey_ joined
20:45 <Habib_> Well, just read the whole thing.
20:45 <jle`> Habib_: (found, other) wouldn't work
20:45 <mauke> @unpl \search -> first listToMaybe . partition (\x -> chname x == search)
20:45 <lambdabot> \ search x -> first listToMaybe (partition (\ x0 -> chname x0 == search) x)
20:45 <mauke> jle`: why not?
20:45 <jle`> oh wait, yeah, it would
20:45 <jle`> heh
20:45 <jle`> was overthinking it :)
20:46 qqwy joined
20:46 <Habib_> If found is Nothing, that means other is equal to cs, because none of the cs are equivalent to what you're trying to find, so the filter returns all the cs.
20:46 <Habib_> So, (found, cs)
20:47 <Habib_> or (found, other), sorry
20:47 <Habib_> grayhatter, the where clause should remain, but the whole isJust block can be collapsed to (found, other)
20:48 <mauke> I think the where clause should be removed and replaced by partition
20:48 Noldorin joined
20:48 <Habib_> Let me look up partition.
20:49 <mauke> :t partition
20:49 <lambdabot> (a -> Bool) -> [a] -> ([a], [a])
20:49 <Habib_> Ah, yeah, that might be good, and then the listToMaybe you thought is probably good too
20:49 <mauke> it takes a predicate and a list, and returns two lists: the elements that pass the predicate, and the elements that don't
20:49 <Habib_> Yeah, just looked it up on hoogle
20:49 Swizec joined
20:50 <Habib_> Yeah, I think mauke's version might be best, although I don't like the listToMaybe function.
20:50 <mauke> why not?
20:51 ajhager joined
20:52 <Habib_> I don't know, it seems like the intent is to be used when you know that only one result can ever be returned, but then in that case, I'd say just use a function which returns Just that first result or Nothing. It feels like coercion to me and if you end up finding more than one result, you'd never know.
20:52 <Habib_> With find, it's more intention revealing, its whole purpose is to only find the first result.
20:52 AleXoundOS joined
20:52 <mauke> no, it's used when you only care about one result and want to throw away the rest
20:53 _cyril_ joined
20:53 <Habib_> Yeah, that's a fair point, but its intent is not as clear as find, IMO, but I agree with you that it's perfect to be used for this scenario. The version with find is just much longer.
20:54 mettekou joined
20:54 <jle`> hm i've only ever used listToMaybe to take the first result and throw away the rest
20:55 curious_corn joined
20:55 <jle`> i've never used it in the case where i know i only have one result
20:55 <mauke> a.k.a. safeHead :-)
20:55 <Habib_> Tht's fair, but I could conceivably see it being used in that situation by someone.
20:55 <jle`> yes, that would be a useful application :)
20:55 Ayey_ joined
20:55 <jle`> but one of many :o
20:56 <Habib_> I use Protolude to make Prelude safer.
20:56 <Habib_> I thought the whole point of Haskell was its safety, then I find out you can have partial functions.
20:56 <dylukes> Partial functions can be handy though.
20:56 <dylukes> In Scala they're really useful for exception handling for example.
20:57 <Habib_> Not only that, but that the default imported functions are often partial.
20:57 <dylukes> Or registering event handlers.
20:57 <jle`> yes i am disturbed that so many partial functions are in Prelude
20:57 <Habib_> dylukes, really? I can't imagine how.
20:57 codesoup joined
20:57 <jle`> even if they are used that way in scala, they aren't used that way in haskell, so it doesn't really make sense to put them in Prelude
20:57 <dylukes> jle`I agree there.
20:58 <Habib_> I don't understand the `error` function either. It seems like an IO action, but it has the type String -> a.
20:58 <jle`> error is not an IO action
20:58 <Habib_> Well, GHC says that, too, but it seems to behave like one to me.
20:58 <jle`> in what way?
20:58 <kadoban> I don't really mind the partial functions in Prelude. It's annoying that some of them don't have a safe alternative though.
20:59 ziocroc joined
20:59 <dylukes> jle`that's not really true though.
20:59 zcourts joined
20:59 <Habib_> Well, it seems to stop further execution, behaving like an exception.
20:59 <dylukes> error ues CallStack, and currentCallStack is an IO action.
20:59 <dylukes> uses*
20:59 <dylukes> It just hides it because it terminates the program so any further unsafety probably doesn't matter.
20:59 <dylukes> Getting the current call stack state is absolutely IO though.
20:59 <Habib_> Ah, so that's why it has that a return value.
20:59 <Habib_> String -> a
21:00 <jle`> dylukes: that's an implementation detail, though
21:00 <jle`> it doesn't have the semantics of an IO action
21:00 <jle`> a lot of things in haskell are implemented using IO underneath...
21:00 <Habib_> It does, though. That's why I 'felt' like it was an IO action without being told.
21:00 <jle`> are you going to call (+) an IO action?
21:00 <Habib_> No, why would I?
21:00 plugin joined
21:01 <jle`> (addressing dylukes) because (+) for Int is implemented using IO underneath
21:01 <jle`> but that doesn't make 2 + 4 an IO action
21:01 <dylukes> I don't think that's a fair comparison.
21:01 <dylukes> (+) doesn't change control flow.
21:01 <dylukes> error very clearly does (it ends it).
21:02 <jle`> that's a better argument than your previous one
21:02 <Habib_> I mean, technically the type signature for error doesn't say it's *not* an IO action.
21:02 <Habib_> It just says the return value could be anything.
21:02 <jle`> semantically in haskell, error "string" is bottom
21:02 <jle`> it's a pure value
21:02 <jle`> in haskell semantics, 'error "msg"' is indistinguishable from a nonterminating computation
21:02 <Habib_> But then if it did return an IO action, it wouldn't be executed straight away.
21:02 <dylukes> jle`That makes sense.
21:03 <dylukes> Except error terminates the program immediately ;p. (I know, semantics)
21:03 alx741 joined
21:03 <jle`> so, `error "msg"` can be thought of in Haskell as a way of creating a more useful bottom
21:03 <jle`> because you can hide bottom anywhere in your code already
21:03 <jle`> head [] = let x = x in x
21:03 <dylukes> Reminds me of ML exceptions.
21:03 <jle`> `let x = x in x` and `error "msg"` are semantically identical
21:03 <Habib_> That's true. I never use error, but I do use undefined when I know what the types are going to be, but not the definitions yet.
21:04 <jle`> but GHC, the compiler, can take advantage of the fact that the bottom was defined using 'error'
21:04 <Habib_> And I want to test part of the program without having to fully flesh things out.
21:04 Ayey_ joined
21:05 <dylukes> jle`is there a canonical monograph/single reference on Haskell's denotational semantics?
21:05 mr_sm1th joined
21:05 <dylukes> I reimplemented STG in high school (for shits-and-gigs and so I wouldn't have to do a less interesting senior project) on LLVM, which was fun.
21:05 <jle`> dylukes: there's the Haskell report
21:05 <dylukes> But, I've neglected the denotational side.
21:06 <jle`> "is there a canonical X about haskell?" => the answer is usually the Haskell report
21:06 the|auriscope joined
21:06 <dylukes> All I saw in the HR was discussion of informal semantics.
21:07 <jle`> there isn't anything other than the report about haskell the language :/
21:07 <jle`> it's basically the only canon
21:07 <jle`> anything else is fanfiction
21:07 <dylukes> I was about to say "and our warmly held hopes and dreams".
21:07 <jle`> or "legends" i suppose
21:07 curious_corn joined
21:08 Luke joined
21:08 <dylukes> "The Legend of Haskell: Link's unsafeAwakening"?
21:08 <mauke> legend: that which ought to be read
21:08 mattyw joined
21:09 <dylukes> In the distant future archeologists will discover troves of flash media filled with literate haskell, relics of a long forgotten civilization.
21:09 JoshS joined
21:09 <jle`> Habib_: IO actions describe programs, but error "msg" doesn't describe any program. it's semantically identical to `let x = x in x`, except GHC can be smarter when trying to evaluate it
21:10 <dylukes> The end came too soon for this influential and advanced society. It had seemed wise to allow arbitrary unicode codepoints as names... but their folly was their demie, as increasingly new haskellers refused to use anything other than emoji.
21:10 <dylukes> New weekend project: reimplement Prelude using only emoji.
21:10 <shapr> dylukes: I'll send money
21:10 <jle`> https://twitter.com/EmojiHaskell
21:10 <dylukes> Jesus christ.
21:10 <dylukes> Why am I not surprised this exists.
21:10 <jle`> although some of their tweets aren't valid haskell which sort of defeats the purpose to me
21:11 Ayey_ joined
21:11 <dylukes> But those are variable names....
21:11 <dylukes> I'm more interested in say, defining the list operations with emoji that actually make sense.
21:11 <mauke> where's the hieroglyph one?
21:11 <jle`> there are some data types there that have names that are emojis
21:11 adraenwan joined
21:12 <jle`> data ?????? ?????? where
21:12 <jle`> ?????? :: ?????? ???
21:12 <jle`> ?????? :: ?????? -> ?????? ?????? -> ?????? a
21:12 <jle`> huh something got mangled up during the pasting
21:12 <mauke> dylukes: https://twitter.com/t3xtm0de/status/600711130324008961
21:12 <mauke> the fun part is those identifiers actually make sense
21:12 <dylukes> Oh that's perfect.
21:12 <MarcelineVQ> yeah, some of the ? symbols became dots and arrows
21:13 <dylukes> mauke am I reading the type correctly:
21:13 tfc joined
21:13 <dylukes> "Given a function that rips a leg off a bird, and a list of birds, yield a list of legs."
21:13 <dylukes> a slug tha rips bird's legs off*
21:13 ptek joined
21:13 <dylukes> a slug that rips birds' legs off*
21:14 Jesin joined
21:14 <dylukes> mauke also, the cliche... "are you sure that isn't perl?"
21:14 <mauke> ... have you seen haskell code before? haskell uses at least as much punctuation as perl
21:14 minn joined
21:14 <maerwald> mauke: nah, we use `fmap` :P
21:15 <mauke> <$>
21:15 <dylukes> (.)
21:15 ubsan_ joined
21:15 <dylukes> The fmap/map thing is still a huge wart to me.
21:15 <dylukes> Is there any reason beyond legacy for that still being split?
21:16 <maerwald> you mean you want: map with the type signature of fmap?
21:16 <mauke> IIRC those hieroglyphics are transliterations of the usual english variables
21:16 <geekosaur> fear of existing programs breaking because of unexpected polymorphism, I think
21:16 <mauke> the function name was something like "m-p"
21:16 <dylukes> Yeah, that's what I thought geekosaur.
21:16 <jle`> well ... map actually used to be fmap. the split happened late into haskell development
21:17 <geekosaur> same reason everyone wants ScopedTypeVariables by default but it never happens
21:17 <dylukes> jle` everything changed when the fmap kingdom attacked.
21:17 <jle`> so the split actually broke some legacy code
21:17 <jle`> at the time
21:17 <jle`> for a long time map was generalized to use all functors but then enough people were unhappy that they split off the two
21:18 <dylukes> Why were they unhappy?
21:18 <jle`> error messages for newbies i think
21:18 <monochrom> History is a dialectic struggle between map=fmap and map≠fmap. :)
21:18 <jle`> but it is clear these days that "error messages for newbies" is no longer a priority, ever since the FTP side won
21:18 <jle`> maybe the argument should be that making map = fmap will actually fix legacy code
21:19 <jle`> code written from before the split will now work
21:19 <jle`> :)
21:19 Ayey_ joined
21:19 <monochrom> I support it! :)
21:19 structur_ joined
21:19 <monochrom> More thorny is whether (.) = fmap :)
21:19 <jle`> make legacy code work again, by generalizing map!
21:19 yellowj joined
21:19 bjz joined
21:19 <monochrom> Make legacy code great again :)
21:19 <dylukes> (.).(.) = fmap fmap fmap which is onomatopoetically pleasing.
21:20 <monochrom> (+) . [1,2,3] <*> [4,5,6]
21:20 <jle`> we can just use <$> everywhere instead
21:20 <jle`> <$> is associative, remember, just like .!
21:20 <jle`> f <$> (g <$> h) = (f <$> g) <$> h
21:21 esad joined
21:21 <jle`> the only problem is the fixity
21:21 <monochrom> "Hi I'm a beginner. What's the difference between 'sin <$> cos $ 4" and "sin $ cos $ 4"? :)
21:21 <Habib_> sin <$> cos $ 4 doens't work
21:22 <dylukes> Yes it does?
21:22 <jle`> > sin <$> cos $ 4
21:22 <lambdabot> -0.6080830096407656
21:22 <Habib_> huh
21:22 <jle`> > sin $ cos $ 4
21:22 <lambdabot> -0.6080830096407656
21:22 <jle`> surprise ~
21:22 <monochrom> :)
21:22 <Habib_> okay, sin <$> cos $ 4 fmaps the sin function over cos before applying it to 4
21:22 <dylukes> <$> = map = function composition
21:22 <dylukes> It's (f . g) 4 vs f (g 4)
21:22 <Habib_> Forgot for a second that (-> r) is a Functor
21:23 <jle`> > succ <$> (negate <$> Just 3)
21:23 <lambdabot> Just (-2)
21:23 <jle`> > (succ <$> negate) <$> Just 3
21:23 <lambdabot> Just (-2)
21:23 <jle`> Habib_: (-> r) is not a Functor
21:24 <jle`> you might be thinking about (r ->)
21:24 <Habib_> I'll just stay quiet now.
21:24 _sg joined
21:24 <glguy> Habib_: It's confusing because (r ->) and (-> r) are made-up syntax, neither works in Haskell. (->) r is a Functor, however
21:24 <dylukes> My current weekend project: a haskell engine for working with Pymol.
21:25 <Habib_> Yes, I must have been thinking of (->) r
21:25 <Habib_> Which could be translated to (r ->)
21:25 dylukes2 joined
21:25 <jle`> dylukes: where do you live that it is currently the weekend
21:25 <jle`> ;_;
21:25 <dylukes2> It's not haha.
21:26 <dylukes2> That's just a weekend project.
21:27 <dylukes2> So out of curiosity
21:27 <dylukes2> What's the state of Haskell IDE support?
21:27 Ayey_ joined
21:28 <dylukes2> Emacs support is good but I mostly use Vim these days and Intellisense/IntelliJ completion is addictive haha.
21:28 Levex joined
21:29 <shapr> dylukes2: emacs support is good, I don't know about vim, and there isn't a Haskell-specific IDE that I've seen.
21:29 epsilonhalbe joined
21:29 <oisdk_> dylukes2 I like haskellformac
21:30 <maerwald> there are haskell-specific IDEs
21:31 <dylukes2> I'd rather use Vim haha.
21:31 <dylukes2> shapr: neco-ghc works pretty well, with some limitations.
21:31 <dylukes2> emacs gets all of the love in the FP world much to my chagrin.
21:32 <maerwald> why do you ask for haskell IDEs when you'd rather use vim then -.-
21:32 jmiven joined
21:32 <dylukes> Because I'd rather use vim than the "for haskell" IDEs,
21:32 <maerwald> anyway: http://www.leksah.org/
21:32 <dylukes> which aren't it seems all that well supported or maintained.
21:32 <dylukes> When I tried to use them anyhow.
21:32 <dylukes> I could never get Leksah actually running on OS X properly.
21:32 <maerwald> well, I can't get anything running on OS X properly, so you're probably right
21:33 <shapr> maerwald: be nice
21:33 <maerwald> ?
21:33 faberbrain joined
21:33 <shapr> maerwald: that comes across as sniping at OSX
21:33 <maerwald> I've used OS X for development and that was my experience
21:33 <dylukes> herewegojoker.gif
21:33 moth joined
21:34 <maerwald> and I said "_I_ can't get anything running on OS X"
21:34 <maerwald> that's not sniping
21:34 <brynedwards> haskell-vim-now and this post are probably good for vim http://www.stephendiehl.com/posts/vim_2016.html
21:34 <maerwald> leksah works fine on linux though
21:34 <maerwald> I just dislike the internal editor
21:34 <dylukes> brynedwards that's the basis of my config.
21:34 <dylukes> The problem is that neco-ghc is relatively limited and has some minor warts.
21:34 <maerwald> the yi interface is kinda broken/unmaintained unfortunately, which is the closes you would get to vim
21:34 <dylukes> I would rather have full ghc-mod integration with IntelliJ .
21:35 <dylukes> I'm learning vimscript currently though, so,
21:35 <dylukes> hopefully I can help remedy that situation.
21:35 <shapr> dylukes: hurrah!
21:35 <brynedwards> Haven't tried intellij but there's this http://rikvdkleij.github.io/intellij-haskell/
21:36 <dylukes> shapr I'd like to get declaration scanning implemented at the least.
21:36 <brynedwards> I used to use vim, now use emacs + evi
21:36 <brynedwards> evil*
21:36 Koterpillar joined
21:37 LuckyRawApe joined
21:38 <dylukes> There's this shapr: https://github.com/eagletmt/ghcmod-vim
21:41 mettekou joined
21:41 dylukes2 joined
21:41 atomi joined
21:44 <nak> ok so how the heck do i go about debugging in haskell
21:44 <nak> i have a variable and i just want to print it out
21:44 <nak> or how do i get visibility on what's inside the var?
21:45 <erisco> nak, load up your program in ghci and poke it
21:45 <brynedwards> nak: There's trace from Debug.Trace
21:45 swalladge joined
21:45 asmyers joined
21:45 <nak> erisco: yeah but that's a total pain. my variable is the left hand side of a monad binding
21:46 <nak> csvData <- BL.readFile "batting.csv"
21:46 <nak> let v = decode NoHeader csvData :: Either String (V.Vector BaseballStats)
21:46 <nak> how to get at "v" and see what's in there ?
21:46 <brynedwards> in GHCi: v <- decode NoHeader <$> BL.readFile "batting.csv"
21:46 <erisco> decode NoHeader =<< BL.readFile "batting.csv"
21:46 <nak> cmon tho
21:46 <brynedwards> or that
21:47 PennyNeko joined
21:47 <nak> that
21:47 <erisco> or fmap rather
21:47 <nak> that's so much extra typing. and i can't even copy paste that from my own program
21:47 <nak> i'd have to know all of those extra ways to bend stuff around just to get at it ?
21:47 <brynedwards> you can copy paste both lines and it should be fine
21:47 <erisco> that's how I do it, but there could be other ways, I don't know
21:48 <erisco> there is an interactive debugger but I wasn't so keen on it
21:48 <brynedwards> doing the original two lines one after the other in GHCi would be fine
21:48 <nak> wait are you joking? i can use <- without starting a "do" ??
21:48 <oisdk_> nak how about https://hackage.haskell.org/package/base-4.9.1.0/docs/Debug-Trace.html#v:traceShowId
21:48 <brynedwards> in GHCi, yes
21:48 <* nak> sighs
21:48 <brynedwards> you can do 's <- getLine'
21:48 <brynedwards> :D
21:48 <kuribas> nak: :break in ghci
21:48 wraithm joined
21:49 <nak> oisdk_: i have no idea how to use that
21:49 <heath> https://wiki.haskell.org/BayHac2017
21:50 <nak> Prelude is so different than compiling/running your script
21:50 conal joined
21:50 <nak> that's kind of annoying <- beginner's perspective
21:50 Lord_of_Life joined
21:50 m0rphism joined
21:50 <nak> sorry, not Prelude
21:50 <nak> ghci*
21:50 <geekosaur> perhaps you want runghc?
21:51 <erisco> runhaskell ?
21:51 <nak> lol i have no idea what either of those are
21:51 <erisco> they just compile your program, run it, and clean up
21:51 <oisdk_> when you wrap it around a value it prints the value whenever it's used
21:51 <geekosaur> they do not compile
21:51 Noldorin joined
21:51 tomboy64 joined
21:51 <geekosaur> they use the same bytecode backend ghci uses
21:51 <erisco> okay, I thought they did
21:51 ajhager joined
21:51 <nak> if people debug programs in ghci, then that's what i'll use... but i'm just expressing how it feels very overwhelming that there's a bunch of extra stuff to learn about it
21:52 <nak> and that knowledge is only valuable in ghci
21:52 <geekosaur> but they don't have the ghci ui
21:52 marcopullo joined
21:52 <erisco> there is not a bunch of extra stuff, it is mostly the same
21:53 <erisco> yes, you are implicitly in a do block already, so you can omit another do
21:53 <erisco> but if you use an extra one it doesn't matter
21:53 hiratara joined
21:53 <erisco> so I don't see how that's so confounding
21:53 <nak> oisdk_: i don't even know how to import this module
21:53 <nak> import Debug isn't doing it for me
21:54 <nak> so i'm not "far" enough to know how to use this
21:54 <monochrom> You can choose to never use ghci. Then there is no ghci to learn. Apparently, that's what C programmer chose to do.
21:54 <oisdk_> nak it's Debug.Trace
21:54 <nak> mhm
21:54 louispan joined
21:54 <erisco> you can't be too worried about typing a few characters into ghci
21:54 <monochrom> Did you know: Casio made a handheld calculator that interpreted C.
21:55 mnislaih joined
21:55 <koala_man> wat
21:55 <erisco> as soon as there is something unexpected you're going to be happy to be able to rapidly experiment
21:55 <monochrom> Wish I had the money to buy one back then, so I can show it to you now.
21:55 <brynedwards> I think temple OS has a C interpreter
21:55 <erisco> it works like your terminal so that you can use the up arrow to re-enter previous lines
21:55 <brynedwards> among other things...
21:55 <koala_man> that would have been so much better than the weird Basic variant mine had
21:55 <nak> erisco: it does "worry" me when the expression to type is completely different than the program i've written
21:55 <monochrom> I agree!
21:55 <nak> erisco: but yes, in this case i learned that i can just paste the lines verbatim
21:55 <erisco> but it isn't completely different...
21:56 darjeeling_ joined
21:56 <erisco> and you can write it exactly the same, including the line returns, if you want
21:56 dni_ joined
21:56 <erisco> I just made a conversion from do-notation so it was more easily entered as a single line
21:56 <koala_man> Basic didn't even let you abstract over vectors. you had to choose a one-letter name and hope no one else used the same one while there was data in it
21:56 <erisco> but if you're not comfortable with that you don't have to
21:57 <nak> erisco: ok so how about writing a function in ghci
21:57 <nak> f :: Int -> Int -> Int
21:57 <nak> f x y = x + y
21:57 <nak> if i linebreak that in ghci, it freaks out
21:58 cmdd joined
21:58 <erisco> you can enter multi-line mode, or you can use a semicolon
21:58 <nak> how to multiline mode ?
21:58 <erisco> or you can omit the type
21:58 Sh4pe joined
21:58 <erisco> :{
21:58 <nak> is that a sad face ^_^
21:58 <monochrom> Begin with :{ , end with :}
21:59 <monochrom> Did you know: (: This is a comment in XPath :)
21:59 <erisco> if you omit the type a different one will be inferred, but usually you'd be alright with leaving it out
21:59 <nak> ok cool re: multiline mode
22:00 t0by joined
22:00 <nak> i wouldn't use the semicolon because that would mean i can't copy/paste from my program into ghci
22:00 JoshS joined
22:00 <monochrom> Why copy? :load exists.
22:00 <erisco> well I am not usually doing that either, I just have my program loaded in ghci
22:00 Ayey_ joined
22:01 <erisco> you can :load or you can list your files as arguments to the ghci program
22:01 <monochrom> To be fair, I acknowledge that there is 1% of the time when pasting is better.
22:02 eschnett joined
22:02 <brynedwards> Must remember to use :break more often...
22:02 <erisco> the typical workflow is evaluate, edit, :r, repeat
22:03 <nak> where can i use break brynedwards ?
22:04 <nak> ok so type of my v is v :: Either String (V.Vector BaseballStats)
22:04 <nak> if it try to display the entire value, it's way too f big
22:04 <nak> so how can i poke around it ?
22:04 <nak> it's an Either, so it's a Right or a Left value
22:04 <Koterpillar> :t isLeft
22:04 <lambdabot> Either a b -> Bool
22:05 <nak> maybe fmap fst v to get the first value of the vector ?
22:05 meoblast001 joined
22:05 cdg joined
22:05 <brynedwards> I would do let (Right csvData) = v
22:05 ubsan_ joined
22:05 <brynedwards> Or something
22:05 hamishmack joined
22:06 <nak> but that's uninteresting to me. i need to know what v is after csvData was decoded
22:06 <brynedwards> fst is for tuples
22:07 <brynedwards> Perhaps csvData was a bad choice there, since you used it earlier
22:07 <brynedwards> I meant a new variable, that would unwrap the Either
22:07 <nak> i know its type, but like, that's still confusing to me. i would like to make an association in my mind of waht the data *values* look like compared to the *type*
22:07 juri_ joined
22:07 <brynedwards> let (Right myVar) = v
22:08 <brynedwards> myVar :: V.Vector BaseballStats
22:08 colton[m] joined
22:09 <brynedwards> Then you could do `V.head myVar` to see the first BaseballStats
22:09 <nak> !
22:09 <nak> ok sweet
22:09 <nak> so (Right myVar) is a pattern match on v
22:09 rgc joined
22:10 zcourts_ joined
22:10 <nak> if v were a Left, myVar would not have been assigned, correct ?
22:11 dan_f joined
22:11 <geekosaur> nak, it should throw an exception about a pattern not being matched
22:11 <brynedwards> @let x = Left 3
22:11 <lambdabot> Defined.
22:11 <brynedwards> @let (Right y) = x
22:12 <lambdabot> .L.hs:180:13: error:
22:12 <lambdabot> Ambiguous occurrence ‘x’
22:12 <lambdabot> It could refer to either ‘Debug.SimpleReflect.x’,
22:12 <monochrom> if v is a Left, and enough evaluation happens to find it out, then there will be what geekosaur said.
22:12 silver_ joined
22:12 <brynedwards> @let somethingElseThen = Left 3
22:12 <lambdabot> Defined.
22:12 wraithm joined
22:12 leshow joined
22:12 <monochrom> However, "enough evaluation" does not always happen.
22:12 <geekosaur> ^
22:12 xaviergmail_ joined
22:12 <brynedwards> @let (Right notSafe) = somethingElseTHen
22:12 <lambdabot> .L.hs:183:19: error:
22:12 <lambdabot> • Variable not in scope: somethingElseTHen :: Either t0 t
22:12 <lambdabot> • Perhaps you meant ‘somethingElseThen’ (line 182)
22:12 <brynedwards> @let (Right notSafe) = somethingElseThen
22:12 <lambdabot> Defined.
22:13 <brynedwards> > notSafe
22:13 <geekosaur> let bindings are lazy, you need to use something bound by the pattern to find out
22:13 <lambdabot> *Exception: /tmp/mueval89369871982275856.hs:183:1-35: Irrefutable pattern fa...
22:13 <nak> ok well i'm happy i found at least some way to look at the data
22:13 <nak> well, i didn't find it
22:13 <nak> you all helped ^_^
22:13 <monochrom> Also, it turns out that the meaning of "enough evaluation" is rather subtle, even for those who understand lazy evaluation.
22:14 <geekosaur> https://twitter.com/deech/status/842110948378828802 not *quite* offtopic...
22:14 <monochrom> http://lpaste.net/100588 shows a subtle and surprising example
22:15 <nak> ok i have to get running. i'll be back a little later. thanks everyone
22:15 <monochrom> Basically "let y@(x:xs) = [] in but but but I am not evaluating x or xs, I am just evaluating y!"
22:16 <* geekosaur> assumes pattern evaluation is all or nothing, so that behavior makes sense
22:16 raynold joined
22:17 <geekosaur> (or put otherwise for this example, the as-pattern binding "doesn't exist" until (x:xs) has been matched)
22:18 AleXoundOS joined
22:18 Frankablu joined
22:21 <dmwit> > let Right x = Left 3 in x :: String
22:21 <lambdabot> "*Exception: <interactive>:3:5-20: Irrefutable pattern failed for pattern Ri...
22:21 Frankablu joined
22:21 <dmwit> No need for long `somethingElseThen` names. ;-)
22:22 <erisco> I don't follow lines 11-14
22:22 <erisco> not a clue what they're doing there
22:23 <monochrom> lines 11-14 of my calculation?
22:23 <erisco> whoever wrote the pastebin
22:23 <brynedwards> Yeah I realised that a minute after my typos
22:23 <monochrom> Yes that's me.
22:24 <monochrom> It applies Haskell 2010 Report section 3.17.3 rule (d).
22:24 <monochrom> You will probably need to read that rule to see.
22:24 halogenandtoast joined
22:25 <monochrom> But it is the main rule characterizing ~
22:25 DarkNoys joined
22:25 <erisco> oh I completely misread the parens
22:25 <monochrom> Oh heh OK!
22:26 <monochrom> Yeah passing 3 parameters to a function, but each parameter is pretty long.
22:26 <monochrom> And the function ends up ignore 2 of them.
22:26 bjz joined
22:28 <erisco> so it is really that rule specifically that kills it
22:29 Ayey_ joined
22:29 <jle`> wouldn't it be nice if there was (Num a, Num b) => Num (a, b)
22:29 <jle`> can you imagine tho
22:29 <jle`> (i could)
22:30 <erisco> well then also the meaning of the let binding
22:30 <erisco> how does it work for functions then, hm
22:30 rgr joined
22:30 freeside joined
22:31 hiratara joined
22:31 jmnoz[m] joined
22:32 freechips joined
22:33 vektorweg1 joined
22:33 <erisco> meh I can't be bothered to find it
22:34 faberbrain joined
22:35 <erisco> I'd expect the same thing though, I assume you get the same case expression
22:35 <geekosaur> jle`, I've seen it used in production code at least once. otherwise it's a generalization of Data.Complex :p
22:36 <geekosaur> (well, that's one way to interpret it at least)
22:36 Darwin226 joined
22:37 Sgeo joined
22:37 boccato joined
22:38 <Darwin226> So I'm doing `stack install cabal-helper-0.7.3.0` and it's giving me a dependency error say that "cabal-helper-0.7.2.0" depends on some specific version of directory. But I'm not installing that version of cabal-helper. Is this a bug?
22:38 JeanCarloMachado joined
22:40 pera joined
22:40 <conal> jle`: https://hackage.haskell.org/package/NumInstances has Num instances for tuples and functions.
22:40 marsam joined
22:41 Ayey_ joined
22:42 <jle`> wouldn't dare use it for a library though
22:42 <monochrom> I have a cunning plan! Num (a,b) uses complex number multiplication, Num (a,b,c) uses vector cross-product multiplication, and Num (a,b,c,d) uses quaternion multiplication.
22:43 <lyxia> Definitely a good idea.
22:43 sssilver joined
22:43 oisdk joined
22:43 <freeside> haha
22:43 <* jle`> wonders if the dimensions actually line up properly
22:44 <twanvl> You'd need to multiply a's with b's, though
22:44 <jle`> i don't think they do unfortunately
22:44 <jle`> yeah
22:44 psychicist__ joined
22:44 <jle`> but a+ for creativity
22:45 <freeside> Num ((Num a, Num b), (Num c, Num d))
22:45 <monochrom> The problem with cunning plans. :)
22:45 <freeside> what could possibly go wrong
22:45 <freeside> or did i mean Num (Num (a, b), Num (c, d))
22:45 <pikajude> yeah, when can we put constraints in nested tuples
22:46 <jle`> you meant neither
22:46 Voldenet joined
22:46 Voldenet joined
22:46 <oisdk> Is there a package out there for church-list kinds of things? Like a left-fold church list? Basically https://hackage.haskell.org/package/foldl-1.2.3/docs/Control-Foldl.html#t:Fold without the b parameter
22:46 <monochrom> You mean Num ((a,b), (c,d)) (with unsaid contraints)
22:47 <rbnnn> I'll try again: Does anyone have resources on how a functional language differs on a low level from for example java? What optimizations can the compiler make when everything is pure? The question I asked earlier makes me realize I have no idea what's going on and my assumptions are wrong, I thought a functional language copies stuff all the time.
22:47 <Koterpillar> rbnnn: http://joeduffyblog.com/2015/11/03/blogging-about-midori/
22:48 <mauke> being pure means you never have to copy anything because nothing is ever modified
22:48 Snircle joined
22:48 <mauke> (this is a bit of a lie)
22:48 <geekosaur> most of what a pure functional language copies is pointers
22:48 <monochrom> rbnnn: https://github.com/takenobu-hs/haskell-ghc-illustrated may help
22:48 <geekosaur> and it does so more often than actual data because purity means it knows when some piece of data is immutable and just copying the pointer is safe
22:50 yamadapc joined
22:50 coltfred joined
22:51 metalbot joined
22:53 marsam joined
22:53 <rbnnn> Koterpillar: that looks very interesting, touches on all the right buzzwords I want to know about :D, moonchrom: I am too much of a novice for something that technical
22:54 <Koterpillar> rbnnn: if something isn't written to, you can pass it by reference
22:54 <Koterpillar> and if you can compute it beforehand, you can inline more
22:54 greatBigDot joined
22:55 a3Dman joined
22:56 <rbnnn> Koterpillar awesome, if I understand correctly "not written to" is equivalent to a chained function in js, like .map(someFunc).map(someOtherFunc)?
22:56 bungoman_ joined
22:56 plugin joined
22:57 <Koterpillar> var x = 1; x = 2; /* x is written to */
22:57 <Koterpillar> const x = 1; x = 2; /* error! */
22:57 louispan joined
22:57 <rbnnn> but..
22:57 Habib_ left
22:57 <rbnnn> so written to means immutable?
22:58 <Koterpillar> immutable means the value cannot be changed
22:58 wraithm joined
22:58 mson joined
22:58 <rbnnn> hmm.. I don't see what you're saying.
22:59 <Koterpillar> const x = 1;
22:59 <rbnnn> yes.. sure
22:59 <Koterpillar> now the compiler is free to replace "x" with "1" everywhere
22:59 <rbnnn> cannot be changed
22:59 <rbnnn> yep
22:59 <Koterpillar> instead of making a memory access to x
22:59 <rbnnn> yes
22:59 <Koterpillar> also
22:59 <Koterpillar> var x = 1; f(); print(x);
23:00 <Koterpillar> even though x is mutable, f has no access to it because it's pure
23:00 <rbnnn> yeo
23:00 <rbnnn> *yep
23:00 <Koterpillar> therefore, you can go ahead and replace print(x) with print(1)
23:01 Gurkenglas_ joined
23:01 <rbnnn> uhh.. does your program have both const f and var f? i don't get the last step
23:02 <jle`> i wonder if data families are even relevant anymore now that we have injective type families
23:02 <Koterpillar> there's no const f or var f
23:02 Ayey_ joined
23:02 sobaken joined
23:02 <rbnnn> oh
23:02 <rbnnn> const x and var x
23:02 <rbnnn> my bad
23:03 <erisco> jle`, yes, for singletons at least
23:03 <Koterpillar> ignore all code samples but the last one
23:03 <jle`> does singletons even need data families anymore now that we have injective type families
23:03 <rbnnn> ohhh
23:03 <jle`> i thought singleton being a data family was a hack because of lack of injectivity
23:03 <rbnnn> I get it
23:03 <erisco> I don't know how they're related actually jle`, can you explain?
23:03 <rbnnn> f can't modify x, so it can "jump ahead" no worries
23:04 <jle`> erisco: the reason why Sing is a data family instead of a type family is because we didn't have injective type families
23:04 <erisco> well it'd be a big problem if Sing wasn't open
23:04 ajhager joined
23:04 <erisco> I don't understand that reasoning
23:04 Levex joined
23:04 <Koterpillar> rbnnn: correct!
23:04 <rbnnn> but I still don't get this: >if something isn't written to, you can pass it by reference
23:05 <Koterpillar> OK, let's prepare an example of that
23:05 <jle`> erisco: for what reason do you believe that Sing is a data family instead of a type family?
23:05 greatBigDot left
23:06 <Koterpillar> rbnnn: which languages are you familiar with?
23:06 <rbnnn> js mostly, some java, smallc/pawn a long time ago
23:06 <rbnnn> Is it customary to always mention username? I am new to irc
23:06 <erisco> aesthetics, and injectivity sounds like a help like you mention
23:07 <erisco> but to have an injective type family it must be closed, afaik, and that won't work for Sing
23:07 <freeside> rbnnn: it might be helpful to read https://en.wikipedia.org/wiki/Copy-on-write to put you in the right frame of mind
23:07 <Koterpillar> rbnnn: when there's a few conversations going on, so you know it's for you and not anyone else
23:07 <rbnnn> freeside: will do
23:08 rkazak_ joined
23:08 <jle`> erisco: open type families can be injective
23:08 <erisco> I wasn't aware
23:09 <jle`> no worries, i had to pause and open up ghci to check too heh
23:09 <erisco> then you still have the aesthetics of not needing another name for your singleton type
23:09 vaibhavsagar joined
23:09 coot joined
23:10 <jle`> yeah; so then it's not necessary for implementation, just a stylistic choice at this point
23:10 <jle`> but fwiw singletons does name every singleton type it exports
23:10 <jle`> the singleton type for bool sings is SBool
23:10 <erisco> you can also have data in classes, and that is directly supported by data families
23:10 <rbnnn> freeside: that's amazing! like a lazy copy operation..
23:10 <jle`> but it does this out of choice and not necessity, which makes me think that avoiding naming is not a priority
23:10 yamadapc joined
23:11 <jle`> oh, can associated tpyes not be injective?
23:11 mizu_no_oto joined
23:11 kvda joined
23:11 <jle`> it looks like associated types can be injective
23:11 <erisco> what is an associated type?
23:12 <jle`> type families associated with type classes
23:12 <jle`> (that's what i thought you were talking about, at least)
23:12 <nshepperd> you can make a data family an instance of a type class
23:12 <jle`> oh, i see
23:12 <erisco> you can have types in classes as well which correspond to type families
23:12 <erisco> I was talking about data
23:13 cschneid_ joined
23:13 epsilonhalbe left
23:13 <erisco> which corresponds to data families
23:13 louispan joined
23:13 <erisco> it is just a little syntax shuffling but you appreciate it when you need it
23:13 pleax joined
23:14 <freeside> rbnnn: so, in the haskell world where variables are immutable, the way you update state is by creating a new thing that is slightly different from the old thing; but behind the scenes, the compiler knows how to think about the deltas as a copy-on-write kind of problem.
23:14 <freeside> so you don't really have to worry about efficiency most of the time.
23:15 <freeside> http://stackoverflow.com/questions/4265660/updating-a-big-state-fast-in-haskell
23:17 Ayey_ joined
23:17 <rbnnn> freeside: fantastic! I'm a novice programmer but I was thinking the other day about creating chains of parallel/unordered but not concurrent/orderer and not concurrent operations, or more advanced ordering rules of execution, is this the problem that functional programming languages solve also? I kind of feel like it when I'm reading but not sure
23:17 JoshS joined
23:18 <freeside> in the real world, the love of money is the root of all evil.
23:18 <freeside> in software, premature optimization is the root of all evil.
23:19 <freeside> the advice is to first get it right, then make it fast.
23:19 <Rembane> So, what happens if you square it?
23:19 <freeside> you empower evil.
23:19 louispan joined
23:20 Guest11549 joined
23:20 <nshepperd> hm, I wonder why Sing from singletons chose to write it as 'data family Sing (a :: k)' instead of 'Sing (k :: *) (a :: k)'
23:20 <freeside> besides, the smart people working on the layers of the tech stack below your software have already thought much more deeply about code optimization than you ever will; getting it right will match their expectations, and allow you to enjoy their optimizations.
23:20 <nshepperd> I find the explicitly kind indexed version a bit less confusing
23:21 yamadapc joined
23:21 <nshepperd> 'Sing Nat 5' instead of 'Sing (5 :: Nat)'
23:21 <freeside> once you become aware that your computer contains such devilry as https://en.wikipedia.org/wiki/Branch_predictor you will be satisfied to leave the nonobvious optimization to professionals.
23:22 louispan joined
23:22 <rbnnn> hmm, so I should assume the compiler knows best, in a wide sense?
23:22 <rbnnn> like not ever worry about number of function calls
23:23 <mauke> profile-guided worrying
23:23 <freeside> well, you should learn about strict, and you should learn how to instrument your code using things like Criterion.
23:24 <freeside> but before you learn about Criterion, which will help you make it fast, you should learn about Quickcheck, which will help you make it right.
23:24 <rbnnn> oh I haven't started with haskell yet at all
23:24 <orion> In industry/the professional world, how does one come up with QuickCheck properties that should hold in your application? It seems like an art.
23:24 <rbnnn> I'm just interested in the functional thing because I studied some math before I started programming and it makes sense
23:25 <rbnnn> or at least it's similar
23:25 <erisco> orion, well, what do you expect your program to do? test for that
23:25 <Koterpillar> orion: or, what do you expect your program to never do?
23:26 <mauke> never fail, never surrender
23:26 <monochrom> never terminate. :)
23:27 <orion> But that seems like unit testing rather than property testing.
23:27 <erisco> friend wrote something called the immortality protocol which handles interrupts by restoring the state, setting the pointer to the next instruction, and keep going
23:27 <erisco> solved some minor crashes on old games
23:27 <freeside> rbnnn: you could look at the reviews of https://www.amazon.com/Parallel-Concurrent-Programming-Haskell-Multithreaded/dp/1449335942
23:28 dan_f joined
23:28 replay joined
23:28 <mauke> ON ERROR RESUME NEXT
23:29 <freeside> think of writing Quickcheck tests as a giant Wason Card Problem
23:29 louispan joined
23:29 <freeside> testing for things your program should never do is as important as testing for things your program should do
23:30 <erisco> orion, they're related. In unit tests you test the individual cases
23:30 <erisco> and quickcheck does just that, afaik, it just figures out good cases to try
23:30 <erisco> in my opinion you should be writing unit tests in that manner anyways
23:31 <erisco> I know there is a rudimentary thing of a list of inputs and a list of expected outputs but this is a weak way of reasoning about the program
23:31 yamadapc joined
23:32 <erisco> once you decide what your program is supposed to do, it is then quite easy to run through thousands of cases
23:32 vektorweg1 joined
23:33 <erisco> if your program takes two ints it is trivial to take the product of all the ints in a range and run your program on it
23:33 <erisco> afaik what quickcheck adds is inspection on your program to more intelligently choose cases
23:33 <freeside> if you find yourself falling in love with test-driven development, you may be a natural candidate for test-ONLY development: https://community.embarcadero.com/blogs/entry/testonly-development-with-the-z3-theorem-prover-38818
23:34 <erisco> running a hundred-thousand cases is not practical when you have thousands of tests in the suite
23:34 <ggVGc> tests?
23:34 <ggVGc> type system!
23:34 <mauke> embarcadero? are they the ones who are currently running delphi into the ground?
23:36 <orion> erisco: Finding a generalization from individual test cases isn't easy.
23:39 <erisco> that isn't how you start
23:39 <erisco> or at least it isn't how I start
23:40 conal joined
23:40 wtetzner joined
23:41 ystael joined
23:41 skeet70 joined
23:41 ubsan_ joined
23:41 <erisco> for example, if you want to write a sorting algorithm, don't begin with sort [] = [], sort [2,1] = [1,2], sort [1,2,1] = [1,1,2] and so on
23:42 <erisco> begin with how sort xs relates to xs
23:42 raycoll joined
23:42 <MarcelineVQ> hmm, that's quite often what I see reccomended here, starting from the back case and iterating out until a pattern emerges you can abstract
23:42 sellout- joined
23:42 <MarcelineVQ> *base case
23:43 <erisco> we can do this together orion so you can become wise in the art ;)
23:43 <mauke> MarcelineVQ: for testing or for implementing?
23:44 <erisco> the base case may be relevant, sure, and it isn't wrong to think about different cases
23:44 <MarcelineVQ> implementing, hmm I did that thing again where I don't read the scrollback didn't I :X sorry
23:44 <erisco> I am saying you don't want to write a program that satisfies the few cases you've figured out and then try and retrofit some general statement about it
23:44 <erisco> you haven't really understood the objective before you've gone and implemented it
23:44 <orion> erisco: You would check that each subsequent item is greater than the previous.
23:45 <erisco> orion, good start, so then lets think about the implications of this
23:45 <mauke> I think that's half the spec of sort: the result must be non-descending
23:45 <erisco> what you stated is more fancily called "monotonically increasing"
23:45 <orion> Sure.
23:46 <erisco> lets think about what will satisfy this spec
23:46 <erisco> what if I write sort = const []
23:46 <orion> Ok, and that length . sort $ xs == length xs
23:47 <mauke> that's actually a type error but I know what you mean :-)
23:47 <erisco> sort (x:_) = replicate (length xs) x; sort [] = []
23:48 <mauke> sort xs = [ head xs | _ <- xs ]
23:48 <erisco> lets assume replicate and length are defined on Integer... there is genericLength but not a genericReplicate
23:48 <orion> And that every element in (sort xs) exists in xs
23:48 dbmikus joined
23:49 <Koterpillar> the other way around
23:49 <mauke> more generally, you want sort xs to be a permutation of xs
23:49 <jle`> orion: not enough; you also need the correct multiplicities of each item
23:49 <erisco> I won't write out the definition, but we can nub the list (removes duplicates) and pad out the length (using whatever element we want)
23:50 louispan joined
23:50 <Koterpillar> you'll have to sort the result, though
23:50 <mauke> sort xs = take (length xs) (cycle (nub xs))
23:51 <Koterpillar> mauke: not monotonic
23:51 <mauke> > take 0 (cycle [])
23:51 <lambdabot> []
23:51 <erisco> we began with "a sort program" and gave a stab at defining what we mean by "sort" by saying sort xs must be monotonically increasing
23:51 <mauke> yeah, put a real sort around that
23:52 <erisco> and then we attack this proposed meaning by trying to think of ways it doesn't agree with our intent
23:52 lordcirth joined
23:52 <erisco> this is the phase where you want all your mistakes to happen
23:52 <erisco> and we made a few
23:52 justanotheruser joined
23:52 <erisco> you may not have thought of all these problems right away but that is part of the practice
23:53 <erisco> I like to say it in two parts. 1) sort xs must be monotonically increasing, 2) sort xs must be a permutation of xs
23:53 <orion> Sure, I follow.
23:54 rcat joined
23:54 TCZ joined
23:54 <erisco> once we feel that we've really captured what we wanted to mean we go ahead and write the program
23:55 <erisco> and if the type system allows it you can have this spec as part of the type
23:55 arawack joined
23:55 <Koterpillar> A subset of this approach is: write an inefficient version and check that the optimized one produces the same results
23:55 sssilver joined
23:55 <orion> This is a very nice self-contained example, but it's not the world I live in.
23:55 <erisco> sure, the world is dirty, and I don't know what it means to show a popup box
23:55 <orion> In my day to day life I have RESTful APIs written in scotty that consult PostgreSQL databases and send messages to RabbitMQ.
23:56 Renesat joined
23:56 <erisco> so here is how I tackle the practical
23:56 ddere joined
23:56 halogenandtoast joined
23:56 <erisco> as you develop software you will have some libraries/modules/namespaces/APIs/layers/whatever that become deeper, as in more and more depends on them
23:57 FullyFunctional left
23:57 <erisco> as this happens you increase the extent to which you test them
23:57 beerdrop joined
23:57 <erisco> this allows brand new things which have no dependencies to be done quickly and ensures important things are tested
23:57 YongJoon joined
23:57 ramzifu joined
23:58 <erisco> the things that sink to the bottom tend to have simpler parts to them, it isn't just the glue code
23:58 <erisco> and are more ideal to test rigorously
23:58 pmade- joined
23:58 suls joined
23:58 louispan joined