Home liberachat/#haskell: Logs Calendar

Logs: liberachat/#haskell

←Prev  Next→ 1,802,995 events total
2021-07-19 09:08:26 <dminuoso> So 1/0 is actually a well defined value, perhaps unintuitively.
2021-07-19 09:09:18 <dminuoso> But, what you probably meant is:
2021-07-19 09:09:22 <dminuoso> % 1 `div` 0
2021-07-19 09:09:22 <yahb> dminuoso: *** Exception: divide by zero
2021-07-19 09:09:31 <dminuoso> % :t div
2021-07-19 09:09:31 <yahb> dminuoso: Integral a => a -> a -> a
2021-07-19 09:09:46 × Patternmaster quits (~georg@li1192-118.members.linode.com) (Ping timeout: 252 seconds)
2021-07-19 09:09:58 Patternmaster joins (~georg@li1192-118.members.linode.com)
2021-07-19 09:10:02 × pavonia quits (~user@user/siracusa) (Quit: Bye!)
2021-07-19 09:10:04 <albet70> yes, div 0
2021-07-19 09:10:07 <dminuoso> albet70: ^- so yeah, this is a partial computation. We could have also made it non-partial and given it the type `div :: Integral a => a -> a -> Maybe a`, which produces Nothing for that case.
2021-07-19 09:10:30 × jolly quits (~jolly@208.180.97.158) (Ping timeout: 252 seconds)
2021-07-19 09:12:02 <dminuoso> albet70: In general, it's better to encode a failure as `Maybe` or `Either s` rather than producing an error (like div does)
2021-07-19 09:12:34 <dminuoso> albet70: The reason is, you cant catch an `error` sensibly (its impossible in pure code, and you have imprecise error semantics if you try to do this from IO). error is really a sad part in Haskell.
2021-07-19 09:12:55 <dminuoso> But you can catch a Nothing just fine (you just pattern match with case-of)
2021-07-19 09:13:02 <dminuoso> Dont even need IO for that.
2021-07-19 09:14:21 lavaman joins (~lavaman@98.38.249.169)
2021-07-19 09:15:25 <albet70> but haskell does try catch to capture runtime errors like IO error
2021-07-19 09:15:48 <albet70> and IO socket error, how to use Either to detect?
2021-07-19 09:16:01 <dminuoso> haskell does not try and catch runtime errors at all
2021-07-19 09:16:08 <dminuoso> They blow up your entire program
2021-07-19 09:17:30 <dminuoso> You have to explicitly catch them in IO
2021-07-19 09:17:44 <dminuoso> And it's subtly difficult to do this because of lazy evaluation
2021-07-19 09:17:47 <dminuoso> Consider
2021-07-19 09:17:49 <dminuoso> % :t evaluate
2021-07-19 09:17:49 <yahb> dminuoso: a -> IO a
2021-07-19 09:18:39 <dminuoso> This one only evaluates up until WHNF. You could still have errors lingering in not-yet-evaluated parts. There's tricks to get around this, but you need to be aware of this
2021-07-19 09:18:57 × lavaman quits (~lavaman@98.38.249.169) (Ping timeout: 250 seconds)
2021-07-19 09:19:34 <dminuoso> It's why uses of `error` are highly discouraged, since it's completely unclear which library functions could possibly trigger an `error`. The most common one that regularly causes headaches for me is\
2021-07-19 09:19:36 <dminuoso> % :t read
2021-07-19 09:19:36 <yahb> dminuoso: Read a => String -> a
2021-07-19 09:19:56 <dminuoso> If you think about it, it should be dead obvious that this is *very* partial (by very I mean almost all strings produce an invalid result, only very few strings produce a parsable value)
2021-07-19 09:20:24 <dminuoso> But this type of error quickly bubbles up and cant be reasonably caught anymore
2021-07-19 09:20:55 <dminuoso> A way better function instead is:
2021-07-19 09:20:57 <dminuoso> % :t readMaybe
2021-07-19 09:20:57 <yahb> dminuoso: ; <interactive>:1:1: error: Variable not in scope: readMaybe
2021-07-19 09:21:07 <dminuoso> % import Data.Text (readMaybe)
2021-07-19 09:21:07 <yahb> dminuoso: ; <interactive>:1:19: error: Module `Data.Text' does not export `readMaybe'
2021-07-19 09:21:17 <dminuoso> % import Text.Read (readMaybe)
2021-07-19 09:21:18 <yahb> dminuoso:
2021-07-19 09:21:19 <dminuoso> % :t readMaybe
2021-07-19 09:21:19 <yahb> dminuoso: Read a => String -> Maybe a
2021-07-19 09:27:02 rahguzar joins (~rahguzar@dynamic-adsl-94-34-39-251.clienti.tiscali.it)
2021-07-19 09:27:55 azeem joins (~azeem@dynamic-adsl-94-34-39-251.clienti.tiscali.it)
2021-07-19 09:28:04 × rahguzar quits (~rahguzar@dynamic-adsl-94-34-39-251.clienti.tiscali.it) (Client Quit)
2021-07-19 09:35:05 × dibblego quits (~dibblego@haskell/developer/dibblego) (Excess Flood)
2021-07-19 09:35:22 dibblego joins (~dibblego@122-199-1-30.ip4.superloop.com)
2021-07-19 09:35:22 × dibblego quits (~dibblego@122-199-1-30.ip4.superloop.com) (Changing host)
2021-07-19 09:35:22 dibblego joins (~dibblego@haskell/developer/dibblego)
2021-07-19 09:39:05 × tom__ quits (~tom@2a00:23c8:9700:8001:a918:fa2c:4713:fcbd) (Remote host closed the connection)
2021-07-19 09:41:07 × MQ-17J quits (~MQ-17J@d14-69-206-129.try.wideopenwest.com) (Ping timeout: 246 seconds)
2021-07-19 09:45:03 dunj3 joins (~dunj3@2001:16b8:3046:8200:9324:28de:5bca:d5dc)
2021-07-19 09:45:16 MQ-17J joins (~MQ-17J@d14-69-206-129.try.wideopenwest.com)
2021-07-19 09:47:09 × yauhsien quits (~yauhsien@61-231-35-149.dynamic-ip.hinet.net) (Remote host closed the connection)
2021-07-19 09:47:45 × peterhil quits (~peterhil@mobile-access-b04801-219.dhcp.inet.fi) (Ping timeout: 268 seconds)
2021-07-19 09:48:35 lavaman joins (~lavaman@98.38.249.169)
2021-07-19 09:49:15 jumper149 joins (~jumper149@80.240.31.34)
2021-07-19 09:53:01 × lavaman quits (~lavaman@98.38.249.169) (Ping timeout: 246 seconds)
2021-07-19 10:06:07 <guest719> dminuoso about traverse "<dminuoso> Say you have a tree, and you want to process each node - but in a way that if you generate an error at any, that the entire computation is considered failed." could we use foldr >=> pure here?
2021-07-19 10:06:36 <guest719> a bunch of function inside a list, then foldr
2021-07-19 10:07:08 <guest719> apply on this tree, if one node failed, then return immediatly
2021-07-19 10:14:45 <jumper149> Is it wrong to say "MonadPlus is obsolete"? Just like `return` is obsolete because of `pure`?
2021-07-19 10:16:00 × eggplantade quits (~Eggplanta@108-201-191-115.lightspeed.sntcca.sbcglobal.net) (Remote host closed the connection)
2021-07-19 10:16:04 × hexfive quits (~eric@50.35.83.177) (Quit: WeeChat 3.0)
2021-07-19 10:16:16 × burnsidesLlama quits (~burnsides@dhcp168-011.wadham.ox.ac.uk) (Remote host closed the connection)
2021-07-19 10:19:15 × xsperry quits (~as@user/xsperry) (Remote host closed the connection)
2021-07-19 10:19:25 Ariakenom joins (~Ariakenom@c83-255-154-140.bredband.tele2.se)
2021-07-19 10:20:44 xsperry joins (~as@user/xsperry)
2021-07-19 10:21:23 peterhil joins (~peterhil@mobile-access-b04801-219.dhcp.inet.fi)
2021-07-19 10:22:22 × jmorris quits (uid433911@id-433911.stonehaven.irccloud.com) (Quit: Connection closed for inactivity)
2021-07-19 10:23:45 moondog joins (~root@185.234.208.208.r.toneticgroup.pl)
2021-07-19 10:25:06 <moondog> hi, quick question, suppose I'd like to parse Haskell files to find particular method calls and it's argument types, where should I start? Is there any tooling for that to avoid writing everything from scratch?
2021-07-19 10:25:24 <dminuoso> guest719: Firstly, `f >=> pure = f`
2021-07-19 10:25:25 Brianmancer joins (~Neuromanc@user/briandamag)
2021-07-19 10:25:44 <dminuoso> guest719: And what you are thinking of already is traverse precisely.
2021-07-19 10:25:47 <dminuoso> % :t traverse
2021-07-19 10:25:47 <yahb> dminuoso: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
2021-07-19 10:26:33 <guest719> dminuoso fmap can't do early exit because it's type, but >>= can do early exit
2021-07-19 10:26:48 <dminuoso> guest719: Yes, and traverse uses >> internally
2021-07-19 10:26:56 <dminuoso> (So it's a bit more general even)
2021-07-19 10:26:56 <guest719> dminuoso I remeber there're different between fmap and >>=
2021-07-19 10:27:10 <dminuoso> % :t (>>)
2021-07-19 10:27:10 <yahb> dminuoso: Monad m => m a -> m b -> m b
2021-07-19 10:27:11 <guest719> >>= can do if-else, and fmap can't do if-else
2021-07-19 10:27:17 <dminuoso> Well, strictly speaking:
2021-07-19 10:27:20 <dminuoso> % :t (*>)
2021-07-19 10:27:20 <yahb> dminuoso: Applicative f => f a -> f b -> f b
2021-07-19 10:27:54 <dminuoso> guest719: `traverse` can be thought to use (*>) internally, which is just an Applicative version of >>
2021-07-19 10:28:04 <dminuoso> Roughly the idea is:
2021-07-19 10:29:17 merijn joins (~merijn@83-160-49-249.ip.xs4all.nl)
2021-07-19 10:29:39 <dminuoso> We take this function (a -> f b) (say `String -> IO Int`)from above, and we `fmap` over the structure (say `[String]`). Then, each value is replaced with a computation of some type (say `IO Int`), so the whole structure then is `[IO Int]`.
2021-07-19 10:29:55 <dibblego> you might be thinking of traverse_
2021-07-19 10:29:58 <dminuoso> Then we `sequence` this, which turns `[IO Int] -> IO [Int]`
2021-07-19 10:32:32 <dminuoso> Imagine this to be: sequence (x:xs) = (:) <$> x <*> sequence xs; sequence [] = pure []
2021-07-19 10:32:58 <dminuoso> dibblego: Ah yeah. I guess that was wrong of me.
2021-07-19 10:33:06 <dminuoso> While I was typing the definition, I realized my mistake.
2021-07-19 10:33:44 <dminuoso> % mySequence (x:xs) = (:) <$> x <*> mySequence xs; mySequence [] = pure []
2021-07-19 10:33:44 <yahb> dminuoso:
2021-07-19 10:33:46 <dminuoso> % :t mySequence
2021-07-19 10:33:46 <yahb> dminuoso: Applicative f => [f a] -> f [a]

All times are in UTC.