melt-umn / silver

An attribute grammar-based programming language for composable language extensions
http://melt.cs.umn.edu/silver/
GNU Lesser General Public License v3.0
59 stars 7 forks source link

Using type classes #401

Open krame505 opened 3 years ago

krame505 commented 3 years ago

Meta-bug to keep track of all the things that we want to change in the standard library once type classes are finished. Some of these are partially doable now and some depend on attribute occurrence constraints.

krame505 commented 3 years ago

Since unlike Haskell we don't have infix operator functions in Silver, what should the equivalents of <*, *> and <*> for the Applicative type class be named?

@remexre any suggestions?

remexre commented 3 years ago

not 2 be wrong but we could just add <*, *>, <*>, <$>, >>=, =<<, >>>, <<<, <=<, >=>, <$, $> as valid names :eyes: (I think these are all the ones I've ever actually used)

for names for the ones you listed, purescript names them ap, applyFirst, and applySecond; I've already got them written up into silver here

krame505 commented 3 years ago

I'm vetoing non-alphanumeric function names (and I'm sure Eric would if I didn't :-P)

Those names seem reasonable.

What's the reason for the seperate Apply and Bind type classes in your library, though? That seems somewhat nonstandard? (I've been mainly referencing Haskell and Idris, btw.)

remexre commented 3 years ago

I've been using PureScript as inspiration. As I understand it, they split them up to reduce the number of laws per typeclass; there might be something in their effect system('s history) that made them want to separate Bind from Applicative though, I'm not sure.

IMO PureScript's break-up of typeclasses is better-designed than Haskell's, though this is mainly because they can remove historical warts (sequenceA), and they split up Num as algebra does.

remexre commented 3 years ago

Counterexamples of Type Classes gives the following examples:

An Apply which is not an Applicative

The constant functor data Const k a = Const k can be made into an Apply (but not an Applicative) whenever k is an instance of Semigroup (but not Monoid).

A Bind which is not a Monad

The Map k data type has an implementation of Bind, since we can implement the map, apply and bind functions, but fails to be a Monad, since we cannot implement pure :: forall k a. a -> Map k a such that the monad laws will hold.

To me the, "keep typeclasses with as few laws as possible" seems the stronger argument, but /shrug

krame505 commented 3 years ago

I see your point, but a potential counterargument is that with the PureScript approach, to define a new instance of Monad, I would need to define instances for 5 classes, which seems like it could be too much.

remexre commented 3 years ago

well, my answer to that one is deriving strategies: you should only have to write the applicative and monad instances, and the others can be derived with the helpers in the appropriate modules.

krame505 commented 3 years ago

I guess this depends somewhat on how much work we want to do with the functor/applicative/monad hierarchy. I wasn't intending to do much with these besides reworking do notation and enabling us to clean up the hard-coded handling in the implicit monads extension. But this is maybe something we can discuss at our meeting tomorrow.

remexre commented 3 years ago

sure; I'd like to go as far as ApplicativeDo, because Validated would be kinda nice... though, maybe equation-level case statements would serve the same purpose (of not having cases in a bunch of attributes + partiality when no value is appropriate).

(Oh, and looks like Scala's cats does the same thing, wrt having a separate Apply and FlatMap trait.)