-
-
Notifications
You must be signed in to change notification settings - Fork 8
church-encoded Free monad #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
This is actually 80% of the reason |
sellout
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @mstksg, looking forward to getting this in.
We’re in the right ballpark now. I showed some ways to integrate this more into the generalized recursion approach. Definitely haven’t done all the work for you, and I can help walk through some of the changes if they’re not clear.
And I know it looks like a bunch of changes, but it’s mostly just taking advantage of the existing library – your semantics stay the same.
| @@ -0,0 +1 @@ | |||
| λ(f : Type → Type) → λ(a : Type) → ∀(r : Type) → (a → r) → (f r → r) → r | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should now look like
λ(f : Type → Type) → λ(a : Type) → ../../Mu/Type (../../FreeF/Type f a)Also, it doesn’t exist on master yet, but I’ve started putting types like this (i.e., recursive types) into a “data/” directory, so this would then be “data/Free/Type”. There are some examples of this on the kind-polymorphism branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, even though the two types are the same, I think there's some benefit in separating the fixed-point from the base functor. Basically like how we have List a and XNor, and we have Natural with Maybe, and we have NonEmpty and AndMaybe. And one benefit in implementing Free directly is that we can work directly with Free as a "normal function", instead of importing an intermediate data type to use it.
(edit: Although, now that I think about it, merge doesn't require importing constructor names, so it'd be possible to "make" a Free value without importing FreeF, but you'd need to import FreeF to use a Free value.)
In the end it might just be a stylistic thing, and I think there could be benefits both ways.
Free/functor
Outdated
| → λ(kf : f r → r) | ||
| → m r (λ(x : a) → kp (g x)) kf | ||
| } | ||
| : Functor (./Type f) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And this can be
λ(f : Type → Type)
→ ../../Mu/functor (../../FreeF/Type f) (../../FreeF/bifunctor f)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trying this out with the alternative representation; this doesn't quite work because it requires Functor f. We can implement it directly using the FreeF implementation, but we just can't do it through Mu FreeF, unfortunately :(
Free/recursive
Outdated
| (λ(x : a) → alg ((FreeF f a b).Pure x)) | ||
| (λ(x : f b) → alg ((FreeF f a b).Free x)) | ||
| } | ||
| : ./../Recursive/Type (./Type f a) (FreeF f a) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be
λ(f : Type → Type)
→ λ(a : Type)
→ ../../Mu/recursive (../../FreeF/Type f a)
Free/retract
Outdated
| monad | ||
| ).join | ||
|
|
||
| in λ(m : ./Type f a) → m (f a) (monad.pure a) (join a) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
λ(f : Type → Type)
→ λ(monad : Monad f) -- note instance immediately after type
→ λ(a : Type)
→ ./recursive.cata
a
( λ(free : ../../FreeF/Type f a (f a))
→ merge { Pure = monad.pure, Free = join } free)and the merge would be cleaner if I ever got my changes into the spec, then it could be
→ ./recursive.cata (f a) (merge { Pure = monad.pure, Free = join })There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically, anything that applies m is going to instead do ./recursive.cata … merge
Free/steppable
Outdated
| embed | ||
| (./../FreeF/functor f functor a) | ||
| } | ||
| : ./../Steppable/Type (./Type f a) (FreeF f a) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
λ(f : Type → Type)
→ λ(a : Type)
→ ../../Mu/steppable (../../FreeF/Type f a)
Free/foldFree
Outdated
| in λ(a : Type) | ||
| → λ(n : ∀(x : Type) → f x → g x) | ||
| → λ(m : ./Type f a) | ||
| → m (g a) (monad.pure a) (λ(q : f (g a)) → join a (n (g a) q)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably look similar to the Free/retract one I proposed.
|
I've made some stylistic adjustments re: imports, and added I've held back from changing |
|
@mstksg Sorry, I didn’t mean to let this languish after your previous response, but I haven’t had a chance to get back to it. To address your most recent point: The requirement of Instead, |
Just following up on FormationAI/dhall-bhat/pull/48 :) Tried my best to shift this to match the format of dada. From the original PR, I've also added
corecursiveand aFreeFbase functor, although I'm not sure where the best place to putFreeFis, or also the best name (I've noticed yaya/dada prefer to have more descriptive names than just MyFunctorF). Let me know if there's anything I can fix!One exception to the explicit style guide mentioned in FormationAI/dhall-bhat/pull/49 is that I sometimes use inline imports in situations that parallel other similar usages in the rest of the repo.