clojure-uk

A place for people in the UK, near the UK, visiting the UK, planning to visit the UK or just vaguely interested to randomly chat about things (often vi and emacs, occasionally clojure). More general the #ldnclj
dharrigan 2021-02-23T07:45:14.009800Z

Good Morning!

mccraigmccraig 2021-02-23T07:53:29.010Z

mΓ₯ning!

djm 2021-02-23T07:54:26.010200Z

πŸ‘‹

jiriknesl 2021-02-23T09:02:38.010400Z

Good morning

2021-02-23T09:27:37.010700Z

Morn'

thomas 2021-02-23T09:29:22.010900Z

morning

alexlynham 2021-02-23T09:29:42.011Z

morning

mccraigmccraig 2021-02-23T11:23:55.015600Z

did some more work on bind / catch equivalence @alex.lynham... turns out that if you sub reject for return and catch for bind then reject+`catch` follow the 3 monad laws like return+`bind` ... which makes sense if you think about it - because in an either context reject+`catch` are processing the left branch and short-circuiting the right branch, whereas return+`bind` are processing the right branch and short-circuiting the left branch. haven't quite figured how finally fits into the picture yet

🀯 1
alexlynham 2021-02-23T11:35:41.015900Z

that makes sense

alexlynham 2021-02-23T11:36:20.016Z

isn't finally in that context a fold over the tagged union back into a type that only contains a scalar?

alexlynham 2021-02-23T11:36:58.016100Z

as in, if you have like a ReaderEither eventually you'll fold it down to a Reader to return a single value

alexlynham 2021-02-23T11:37:23.016200Z

where the Reader is the product of either left or right of the ReaderEither

alexlynham 2021-02-23T11:37:54.016300Z

so finally is just a function that lifts into the Reader context in the fold action and helps deliver that final type?

mccraigmccraig 2021-02-23T11:50:11.019900Z

no, finally is a bit odd - it's got a similar signature to bind, but throws away the result of the fn like m a -> (a -> m b) -> m a while preserving other effects (like writer log, state etc)

alexlynham 2021-02-23T11:51:42.020100Z

right, but a closure with finally in it will return a value

mccraigmccraig 2021-02-23T11:53:01.021Z

yes, but always the same value that was put into it, augmented with any effects that were output in the finally block

alexlynham 2021-02-23T11:53:30.021600Z

yeah

mccraigmccraig 2021-02-23T11:53:36.021700Z

it's straightforward to implement, but i haven't figured out if and how it follows any of the associativity laws yet

alexlynham 2021-02-23T11:53:38.021800Z

so it's like identity + side effects

mccraigmccraig 2021-02-23T11:53:51.022200Z

zakly

alexlynham 2021-02-23T11:54:23.022400Z

cos the side effects can only really work on the monadic context i guess

alexlynham 2021-02-23T11:54:24.022500Z

hm

alexlynham 2021-02-23T11:54:28.022600Z

need to ponder further

mccraigmccraig 2021-02-23T11:55:20.023Z

yeah, i'm in ponderland

alexlynham 2021-02-23T11:55:24.023100Z

is there any reason the finally block couldn't accept a binding that operated on the wrapped type passed to the finally block?

alexlynham 2021-02-23T11:55:52.023200Z

i know that maybe i'm a little obsessed with the idea it's just a fold and a lift

2021-02-23T11:59:36.024100Z

Btw @mccraigmccraig, I've added some more detail to our convo as you asked about it, not sure if you have anything to add based on it, if not thanks for your help πŸ˜ƒ...

mccraigmccraig 2021-02-23T12:00:04.024500Z

oh, my bad @folcon - yesterday rather got away with me 😬

1
mccraigmccraig 2021-02-23T12:17:01.025600Z

@alex.lynham the finally fn shouldn't need lifting - it's a regular monadic fn so e.g.

user> (m/with-context rwx/rwexception-ctx
        (-> (m/return "foo")
            (m/bind (fn [s] (m/return (str s "bar"))))
            (m/bind (fn [v] (throw (ex-info "boo" {:v v}))))
            (err/finally (fn [] (w/tell [:finally :happened])))
            (err/catch (fn [e] (m/return (ex-data e))))
            (r/run {})))
{:monad.writer/output {:finally [:happened]}, :monad/val {:v "foobar"}}

alexlynham 2021-02-23T12:45:55.027600Z

oh i meant more in the sense of conceptually mapping it onto fold. probably not easy to get across what i was getting at over text πŸ˜… i see what you're getting at here though

mccraigmccraig 2021-02-23T12:59:40.029600Z

i think i'm aiming towards a re-frame like programming model, with error handling and fx delivery uniform for both sync and async computations

alexlynham 2021-02-23T13:03:24.029700Z

using monads or an effect type?

mccraigmccraig 2021-02-23T13:12:40.030500Z

using a writer monad with an effect-accumulation monoid

mccraigmccraig 2021-02-23T13:13:22.031Z

basically just a map of {effect [effect-val]}

alexlynham 2021-02-23T13:13:24.031100Z

so you can just reduce the effects at will, regardless of whether it's sync or async?

alexlynham 2021-02-23T13:13:55.031300Z

looks suspiciously like a variant type πŸ‘€

mccraigmccraig 2021-02-23T13:14:31.031700Z

no, the map can hold many effect descriptions

alexlynham 2021-02-23T13:15:39.032300Z

why a map?

mccraigmccraig 2021-02-23T13:17:02.033400Z

so {:push [{:token "abc" :message "hey"}] :websocket [{:channel "/users/123" :data {...}}]}

mccraigmccraig 2021-02-23T13:17:37.033700Z

could equally be a list of variants though

alexlynham 2021-02-23T13:18:21.033800Z

seems like the list would be more in keeping with a monoidal interface intuitively? just cos i tend to think of maps as being extendable

alexlynham 2021-02-23T13:19:00.033900Z

...unless that is the intention here

mccraigmccraig 2021-02-23T13:22:39.035400Z

i thought the map of lists was cute 😬... it's just a monoid interface impl though, it's easy to switch out

mccraigmccraig 2021-02-23T13:28:37.038800Z

most of yapster's api and routing function comes down to (using re-frame terminology) receive-event -> fetch-cofx -> process -> write-fx type processes - and currently fetch-cofx, process and write-fx are all mixed up - i'd like a programming model which doesn't require insane amounts of discipline to keep them nicely separated

alexlynham 2021-02-23T13:35:29.039Z

fair

alexlynham 2021-02-23T13:35:58.039100Z

we have two similar things in current codebase

alexlynham 2021-02-23T13:36:30.039200Z

one is xfm data -> write data -> get db driver return -> xfm that into a serialised form

alexlynham 2021-02-23T13:38:03.039300Z

and it is broken down into sorta two generics xfm -> write db driver return -> xfm which can be turned into typed generics where you pass in compatible fns that you want and then you can combine the two inner combinators to an outer one so for most entities you're usually using v similar legos in a v similar order

alexlynham 2021-02-23T13:38:34.039400Z

so we've ended up just abstracting and abstracting, but that has relied on a disciplined effort

alexlynham 2021-02-23T13:39:14.039500Z

it would be easy for a future dev team to completely trip over it if they weren't disciplined, it would get verbose fast

mccraigmccraig 2021-02-23T13:40:52.039700Z

xfm ?

alexlynham 2021-02-23T13:46:01.039800Z

transformation

alexlynham 2021-02-23T13:47:50.040200Z

think i might even have pinched that shorthand from hickey

mccraigmccraig 2021-02-23T13:48:15.040500Z

that was my first guess πŸ™‚ then i realised i wasn't sure

alexlynham 2021-02-23T13:51:39.040600Z

i can tell i've finally snapped after a long winter when i'm writing test fixtures like

{
  groupName: 'badger club',
  bio: 'the first rule of badger club is DO NOT TALK ABOUT BADGER CLUB'
  ...
}

alexlynham 2021-02-23T13:51:57.040700Z

spring can't come soon enough

2021-02-23T21:04:10.043Z

Oh, that doesn't just work? :(....

2021-02-25T10:29:36.080700Z

Ahh...