2025/05/06

Newest at the top

2025-05-06 23:27:53 +0200 <hellwolf> wow, you guys are fast.
2025-05-06 23:26:48 +0200merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 268 seconds)
2025-05-06 23:24:34 +0200tomsmedingis off to bed, that's enough
2025-05-06 23:24:24 +0200tromp(~textual@2001:1c00:3487:1b00:cdc3:f42b:30fc:1c61)
2025-05-06 23:23:37 +0200 <monochrom> Was just talking with a friend who teaches computability and NP-completeness, so let me close with "cannot reduce >>= to <*>" for extra confusion!
2025-05-06 23:23:08 +0200tromp(~textual@2001:1c00:3487:1b00:cdc3:f42b:30fc:1c61) (Quit: My iMac has gone to sleep. ZZZzzz…)
2025-05-06 23:22:25 +0200 <tomsmeding> "cannot implement >>= using <*>" is clearer, IMO
2025-05-06 23:22:06 +0200 <tomsmeding> stupid dualities
2025-05-06 23:22:00 +0200 <tomsmeding> cannot convert <*> to >>=, and cannot convert users of >>= to users of <*>
2025-05-06 23:21:44 +0200 <monochrom> >:)
2025-05-06 23:21:40 +0200 <tomsmeding> sure
2025-05-06 23:21:40 +0200merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-05-06 23:21:38 +0200 <tomsmeding> oh
2025-05-06 23:21:32 +0200 <tomsmeding> (the other way round)
2025-05-06 23:21:19 +0200 <monochrom> Right, cannot convert <*> to >>=
2025-05-06 23:21:12 +0200 <tomsmeding> it's consistent. :)
2025-05-06 23:21:02 +0200 <tomsmeding> hence if you could use (<*>), you can also use (>>=); but if you were using (>>=), you can't necessarily use (<*>) instead
2025-05-06 23:20:42 +0200 <tomsmeding> being in an M context does not help for going the other way
2025-05-06 23:20:19 +0200Moyst(~moyst@user/moyst) Moyst
2025-05-06 23:19:04 +0200 <tomsmeding> monochrom: if you are already in an M context, then you can convert easily from M (a -> b) to a -> M b; to use your types, you are indeed in an M context
2025-05-06 23:17:42 +0200 <tomsmeding> ... oh, in my local ghci the latter version had differently-named type variables)
2025-05-06 23:17:28 +0200 <lambdabot> [a -> b] -> a -> [b]
2025-05-06 23:17:27 +0200 <tomsmeding> :t \l x -> map ($ x) l
2025-05-06 23:17:26 +0200 <tomsmeding> (clearly this is better than
2025-05-06 23:17:25 +0200 <monochrom> I am now trying to reconcile that with how sometimes we say that Monad is an upgrade of Applicative by upgrading M (a -> b) -> M a -> M b to (a -> M b) -> M a -> M b.
2025-05-06 23:17:23 +0200Moyst(~moyst@user/moyst) (Ping timeout: 244 seconds)
2025-05-06 23:17:08 +0200 <lambdabot> [a -> b] -> a -> [b]
2025-05-06 23:17:07 +0200 <tomsmeding> :t (.) <$> flip map <*> const (flip id)
2025-05-06 23:17:04 +0200 <tomsmeding> monochrom: actually, your function is quite okay
2025-05-06 23:15:02 +0200__monty__(~toonn@user/toonn) (Quit: leaving)
2025-05-06 23:14:37 +0200 <tomsmeding> ("that's not readFile")
2025-05-06 23:14:30 +0200 <tomsmeding> the `IO (FilePath -> String)` example also illustrated it quite well, I think
2025-05-06 23:14:29 +0200amadaluzia(~amadaluzi@user/amadaluzia) (Ping timeout: 248 seconds)
2025-05-06 23:13:52 +0200 <monochrom> I guess [a->b] -> a->[b] shows the problem, or at least why you must sacrifice something.
2025-05-06 23:12:20 +0200 <EvanR> though what you CAN do ... is kind of hard to determine without defined IO
2025-05-06 23:12:08 +0200 <EvanR> right
2025-05-06 23:12:00 +0200 <tomsmeding> so as was said already, neither direction is something you can always do :p
2025-05-06 23:11:31 +0200 <tomsmeding> or you would duplicate the effects, which is in general not what you want (but it may be acceptable in some specific circumstances)
2025-05-06 23:11:04 +0200j1n37-(~j1n37@user/j1n37) (Ping timeout: 252 seconds)
2025-05-06 23:10:58 +0200 <tomsmeding> if you're not, then it doesn't work
2025-05-06 23:10:51 +0200 <tomsmeding> if you're in an IO context, you can `\mf -> do f <- mf; return (pure . f)`
2025-05-06 23:10:40 +0200j1n37(~j1n37@user/j1n37) j1n37
2025-05-06 23:10:35 +0200 <EvanR> going the first way you're restricted in the kind of effects you can do
2025-05-06 23:10:27 +0200merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 244 seconds)
2025-05-06 23:10:12 +0200 <EvanR> yeah
2025-05-06 23:10:07 +0200 <tomsmeding> EvanR: you have an `IO (a -> b)` and you need to shove it into an `a -> IO b`-shaped hole?
2025-05-06 23:09:53 +0200 <EvanR> is it a free forgetful situation xD
2025-05-06 23:09:38 +0200 <EvanR> ok what if you go the other way
2025-05-06 23:09:16 +0200 <tomsmeding> while this was kind of already said by other people above, I just wanted to summarise :p
2025-05-06 23:08:41 +0200 <tomsmeding> hellwolf: if you end up needing to shove an `a -> IO b` in an `IO (a -> b)`-shaped hole, then you either need to make the effects in the function you have in hand independent of its `a` input, or, if that cannot be done, change the type of the hole