-
-
Notifications
You must be signed in to change notification settings - Fork 7
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
church-encoded Free monad #8
base: master
Are you sure you want to change the base?
Conversation
This is actually 80% of the reason |
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
corecursive
and aFreeF
base functor, although I'm not sure where the best place to putFreeF
is, 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.