Skip to content
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

Resolve #11. Rename run to applyNT and nat to makeNT #12

Closed
wants to merge 3 commits into from

Conversation

phadej
Copy link
Contributor

@phadej phadej commented Oct 13, 2016

It wasn't clear whether you want to preserve the old names in #11 (comment) so I went ahead and renamed.

If done this way, this is a breaking change.

@RyanGlScott
Copy link
Member

Do these names sound reasonable, @andygill?

@andygill
Copy link
Member

No objection in principle, but this is a non-backwards compatible change. The version # should change to reflect this.

Also, should it be applyNT or runNT? I think runNT, but others know more about this than I do.

@RyanGlScott
Copy link
Member

I'm leaning towards runNT too, if only because I proposed applyNT as the name of this combinator, and I can't think of another name for it :)

@phadej
Copy link
Contributor Author

phadej commented Oct 15, 2016

I see, let's pause and think:

There are two representations of natural transformations, and we need a conversion function between them.
I propose

type to RankNType to newtype
RankNType type f ~> g = forall x. f x -> g x applyNT wrapNT
newtype newtype f :~> g = Nat (forall x. f x -> g x) unwrapNT id

We need applyNT :: (forall x. f x -> g x) -> f y -> g y, because type of id doesn't unify with it (or GHC doens't want to unify, it has good reasons for that).
Otherwise wrapNT / unwrapNT could have been makeNT / applyNT, alternatively mkNT and unNT.

I'll modify the PR with this reasoning and new names, if we agree.


A slight sidetrack:

generics-sop package defines newtype (f -.-> g) a

-- | This is functor exponential
newtype (f -.-> g) a = Fn { apFn :: f a -> g a }

-- | This instance isn't defined anywhere...
instance (Contravariant f, Functor g) => Functor (f -.-> g) where
    fmap f (Fn fg) = Fn (fmap f . fg . contramap f)

-- And we have a new way to write a type for natural transformations
type f ~.~> g = forall x. (f -.-> g) x

-- and if we over-engineer, there are two newtype layers now!
newtype f :~.~> g = ExpNat  (f ~.~> g)

It would be great to have good story how to convert between all of these representations, as f -.-> g is also useful. IFF such type(s) will be added to natural-transformations.

Through Transformation class unwrapNT would be able to also unwrap :~.~>, but not -.->. But that's correct, as -.-> isn't natural transformation!

SO: Should Transformation include a wrapNT method? And if don't, I'll be glad to add a documentation comment about that as well.

instance Transformation f g (f :~> g) where
    Nat f # g = f g
    wrapNT = Nat

instance Transformation f IO (Object f) where
    Object f # g = Nat f # g
    wrapNT = Object

@phadej
Copy link
Contributor Author

phadej commented Oct 15, 2016

Additionally / Alternatively, we could change to:

newtype f :~> g = NT { ($$):: forall x. f x -> g x } -- not Nat

So there would be even less confusion with natural numbers. Then, wrapNT would make sense mostly as a part of Transformation class.

@phadej phadej force-pushed the longer-names branch 3 times, most recently from 899befd to cdff4f0 Compare October 16, 2016 11:40
@phadej
Copy link
Contributor Author

phadej commented Oct 19, 2016

ping @RyanGlScott @andygill

@RyanGlScott
Copy link
Member

Let me preface this by saying that I don't know how I feel about the (-.->)/(~.~>)/(:~.~>) suggestion yet. In any case, I feel that is probably best left to a separate PR, if you wish to pursue it.

You seem to have expanded the scope of this PR since the last time I checked it. In particular, I'm a bit uncomfortable at the idea of making wrapNT a class method of Transformation, if only because I don't think every possible Transformation would admit a wrapNT implementation easily. As an example, we've wanted to add something like this to blank-canvas for a while:

send :: DeviceContext -> Canvas a -> IO a

instance Transformation Canvas IO DeviceContext where
  (#) = send

But if you look at the implementations of send and DeviceContext, it is far from obvious how one would implement wrapNT for it. So I'd prefer to leave it as a function that just works over (:~>).

I'm a weak +1 on the idea of renaming the Nat constructor to NT for consistency's sake.

@andygill
Copy link
Member

I'm not a fan of the wrapNT change, for the same reasons as @RyanGlScott.

On the other hand, I want experimentations like this. We are still trying to get the best natural transformation story for Haskell, and we've not found it yet.

@roboguy13
Copy link
Member

roboguy13 commented Oct 20, 2016

I'm also not sure about wrapNT. Right now, I think of Transformation as saying that there is either a natural transformation "somewhere" in t or t provides a way to build a natural transformation. This is kind of similar to how something like MonadState tells you there is a state "somewhere" in the monad stack. Having a wrapping method is not an issue for MTL-type classes like MonadState because you must have a return method (since they are Monads), but we might not have a requirement like that.

In addition to the example @RyanGlScott gave, what if you have an additional context along with the natural transformation in your type? What if there is no "default" value to put in that context?

@phadej
Copy link
Contributor Author

phadej commented Oct 20, 2016

@RyanGlScott, @andygill, @roboguy13

I reverted wrapNT in Transformation. And also renamed Nat to NT

nat = Nat
-- | An alias to 'id', to help type-inference.
--
-- See <https://github.com/ku-fpg/natural-transformation/issues/9#issuecomment-172121060 comment on GitHub>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of linking to a GitHub comment in the Haddocks, it might be more illustrative to provide a code example which uses applyNT.

@RyanGlScott
Copy link
Member

Looking good, @phadej. Just a couple of more changes I'd recommend (besides the inline comment I made):

  • According to Travis, the test suite is currently failing to build.
  • Let's go ahead and bump the version to 0.4 (and add a changelog note too).

@phadej phadej force-pushed the longer-names branch 2 times, most recently from 307e078 to ac62335 Compare October 21, 2016 05:24
@RyanGlScott
Copy link
Member

Merged in 72f6167. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants