Closed treeowl closed 5 years ago
Ah, neat trick. I didn't know about this. Waiting for travis, then I'll take another look.
@sjakobi what are your thoughts on this? I'm in favour. The only drawback might be that type errors are slightly more confusing, though it's unlikely that users are going to pass anything but a function in practise anyway. also, perhaps the use of this trick should be documented.
I'm not so sure about the type variable name/presentation. I think we should use something infix to suggest a function arrow. Since we can't use actual operator characters in a type variable, maybe something like a `arr` b
?
Or maybe a `to` b
?
Neat idea!
We have the following note in the haddocks:
All of the functions in this module take an argument that solely directs the type of the coercion. The value of this argument is ignored.
So how about something like
type Director a b = a -> b
We could then have haddocks on the type alias.
BTW @chessai, had you seen https://github.com/sjakobi/newtype-generics/pull/5? I sometimes feel bad about having this neat API just lying around. I suspect that it's actually better than what either coercible-utils
or newtype-generics
currently offer.
Neat idea!
We have the following note in the haddocks:
All of the functions in this module take an argument that solely directs the type of the coercion. The value of this argument is ignored.
So how about something like
type Director a b = a -> b
We could then have haddocks on the type alias.
I think I'd prefer something more like type Director p a b = p a b
. That way they could pass anything of kind Type -> Type -> Type
. But, perhaps this flexibility is unnecessary, and
your type alias would be preferred, since the only goal here is clarity of consumption.
I'm not a fan of this Director
business, for two main reasons. One is that I'm opposed to type synonyms in most cases; they add mental indirection for nothing here. Also, I don't even see how that's supposed to be mnemonically helpful here. Much better, I think, to give the type variable a name that indicates what it's supposed to do.
I think the right place to document what the to
/arr
/coerceTo
type variables are about is the documentation at the top of the module.
By the way... if you want to keep precisely the same API as before while still communicating the same thing, one option would be
class IsArrow p | -> p
instance IsArrow (->)
-- or
class IsArrow p where
type Silly p -- banish overlapping instances
instance p ~ (->) => IsArrow p where
type Silly (->) = ()
(#.) :: (Coercible b c, IsArrow p) => p b c -> (a -> b) -> a -> c
(#.) _ = coerce (#.) _ = coerce
This means the argument will be inferred as having a function type, but (#.)
can't make use of that fact. I don't think this is really a good idea, but I figured I'd mention it...
I'm not a fan of this
Director
business, for two main reasons. One is that I'm opposed to type synonyms in most cases; they add mental indirection for nothing here. Also, I don't even see how that's supposed to be mnemonically helpful here. Much better, I think, to give the type variable a name that indicates what it's supposed to do.
I generally share this opinion. Type synonyms are generally distracting, I only like using them for quick hacking. Almost all usage of type synonyms are banned at work, except for the common transformers+Identity story.
Okay, I think we should just name p
to something useful and make it infix.
@chessai, for what it's worth, I have found more uses for type synonyms than that. Several higher-rank ones can be useful, like type f ~> g = forall x. f x -> g x
, and stuff from lens
(though that's always controversial). In heavily typish code they often show up with type families, such as
type family ReverseOnto acc xs where
ReverseOnto acc '[] = acc
ReverseOnto acc (x ': xs) = ReverseOnto (x ': acc) xs
type Reverse xs = ReverseOnto '[] xs
I recently found them useful for working around nasty limitations of the type role system, where sticking a newtype
in how I'd prefer prevented necessary coercions (the whole mess got wrapped under a newtype before exposing it to the world anyway).
My final "approved by me!" use for type synonyms is as throw-away constraint synonyms appearing once as a superclass constraint, once as an instance constraint, and never again.
type CS a b c d = (Blah a, Boop a b, Bleep b c, Huh c d b, .......)
class CS a b c d => C a b c d
instance CS a b c d => C a b c d
Sorry for the irrelevant ramble; can't help myself.
it's ok; i enjoy your rambles. i can see uses for all of those.
Yeah, Director
wasn't a good name.
I'd be fine with something like
a `to` b
or
coerce a b
Although I'd like to see the haddocks before we make the final decision.
I changed the name of the type variable and updated the documentation.
Thank you @treeowl! :)
Following
profunctors
, make the types indicate what's unused.