Using type classes
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.
- [x]
Eqtypeclass- [x] Non-
byfunctions (contains,lookup,union, etc.) - [x] Make
==forward to callingeq - [x] Default instance with
isEqual/isEqualToequality attributes - [x] Refactor Silver equality testing extension
- [x] Non-
- [x]
Ordtypeclass- [x] Non-
byfunctions (sort, etc.) - [x] Make relational operators forward to member functions
- [x] Default instance based on attributes - introduce "ordering attributes" like equality attrs, but using
<instead?
- [x] Non-
- [x]
Convertibletypeclass withtoInteger,toFloat,toString, andtoBoolean, with instances implemented foreign functions - [x]
Monoidtype class- [x] Allow default of monoid attributes to be inferred
- [x]
Functor/Applicative/Monad/MonadFailhierarchy- [x] Fix
do-notation - [x] Refactor implicit monad extension (Dawn?)
- [x] Fix
- [x]
Showtype class withpp :: (Document ::= a)- Have
show :: Show a => (String ::= Integer a) - Default instance for
ppattribute (instance pp {} occurs on a => Show a) - Instance for
Show Documentwherepp = id
- Have
- [ ] Category type class
- [x]
Arbitrarytype class for randomized testing, resurrect/refactor treegen extension - [x] Make
deserializeandrewriteWithbe library functions withreifyable(typeable?) constraint - [ ] Refactor origins using a
trackedconstraint - [x] Refactor standard lib with https://github.com/melt-umn/silver/pull/451
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?
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
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.)
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.
Counterexamples of Type Classes gives the following examples:
An Apply which is not an Applicative
The constant functor
data Const k a = Const kcan 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 kdata type has an implementation ofBind, since we can implement themap,applyandbindfunctions, but fails to be aMonad, since we cannot implementpure :: forall k a. a -> Map k asuch that the monad laws will hold.
To me the, "keep typeclasses with as few laws as possible" seems the stronger argument, but /shrug
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.
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.
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.
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.)