Open krame505 opened 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?
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 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 ofBind
, since we can implement themap
,apply
andbind
functions, but fails to be aMonad
, since we cannot implementpure :: 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
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 case
s 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.)
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.
Eq
typeclassby
functions (contains
,lookup
,union
, etc.)==
forward to callingeq
isEqual/isEqualTo
equality attributesOrd
typeclassby
functions (sort
, etc.)<
instead?Convertible
typeclass withtoInteger
,toFloat
,toString
, andtoBoolean
, with instances implemented foreign functionsMonoid
type classFunctor
/Applicative
/Monad
/MonadFail
hierarchydo
-notationShow
type class withpp :: (Document ::= a)
show :: Show a => (String ::= Integer a)
pp
attribute (instance pp {} occurs on a => Show a
)Show Document
wherepp = id
Arbitrary
type class for randomized testing, resurrect/refactor treegen extensiondeserialize
andrewriteWith
be library functions withreifyable
(typeable
?) constrainttracked
constraint