-
-
Save JoeyEremondi/26de88df1cadbc5347d9 to your computer and use it in GitHub Desktop.
-- interface is a more familiar name for the intention of the construct | |
type alias Append a rest = { rest | append : a -> a -> a} | |
-- implement is a more familiar name | |
stringAppend rest = {rest | append = \x y -> x ++ y} | |
-- this is Monoid | |
type alias AppendWithId a rest = Append a {rest | id : a} | |
-- ^ 1 potential superclass | |
appendWithIdString rest = {rest | id = ""} | |
type alias Eq a rest = | |
{rest | eq : a -> a -> Bool} | |
neq : Eq a rest -> a -> a -> Bool | |
neq inst x y = not <| inst.eq x y | |
concat : AppendWithId a rest -> List a -> a | |
concat inst list = | |
case list of | |
(x::xs) -> | |
inst.append x (concat inst xs) | |
[] -> | |
inst.id | |
foo : Append a rest -> Eq a rest -> a -> a -> a | |
foo ainst einst x y = | |
if neq einst x y then | |
ainst.append x y | |
else | |
x |
HKP and Typeclasses are completely orthogonal
I never said they weren't. Indeed, with HKP we could make these not-typeclasses records work.
What, specifically, is not having HKP stopping you from producing in Elm?
Something along these lines:
type alias Chainable m rest =
{ rest |
constant : a -> m a,
map : (a -> b) -> m a -> m b,
andMap : m (a -> b) -> m a -> m b,
andThen : (a -> m b) -> m a -> m b
}
sequence : Chainable m rest -> m b -> m a -> m b
sequence {andThen} after before =
andThen (\_ -> after) before
map2 : Chainable m rest -> (a -> b -> c) -> m a -> m b -> m c
map2 {map, andMap} f a b =
map f a `andMap` b
As a reminder, the real benefit of type classes is not generic code. We have most of that already thanks to consistent naming across libraries. The benefit is being able to take a small API and build many more useful things on top of it. For example, anything that can be compared can support min
and max
, and a list of comparable things is sortable.
Is the ability to generalize functions over Monads not a sufficient use case?
Monads for monads' sake don't count for anything. See Joey's comment: what can't you build? How is your code adversely affected? Granted, my example isn't really concrete either.
I guess I feel differently, in that monads for monads sake is useful. One of the appeals of working in a functional languages is the many problems are solved for you by useful functions, and reduce cognitive overhead by using simple polymorphic abstractions. sequence
is a great example, if we had sequence
I would not have to write it myself so frequently and for different types. I can do it because I understand this one very well, but I'd not claim that for all the functions I regularly use, nor would I want to demand that level of understanding from others, simply to take advantage of useful abstractions like sequence
or andMap
.
I guess I feel differently, in that monads for monads sake is useful.
This is a complaint as old as Elm itself. I would recommend reading this post from Evan on this subject, and maybe some surrounding context in that thread.
Basically, any lobbying should be rooted in use cases. What, specifically, is not having HKP stopping you from producing in Elm? Or, what negative artifacts / antipatterns are showing up in your code because of it?
Evan definitely won't integrate it just because people think it's a cool feature.