-
-
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 |
I'll take HKP, just so long as there is a way. Since HKP would be nice in more contexts, is a smaller departure, and is a smaller feature, HKP first sounds nice and conservative. Then a more informed estimation is possible, after seeing how dictionary passing works in practice. Is there a way I can lobby for HKP as a feature?
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.
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` bAs 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.
True, but I stand by my opinion that HKP and Typeclasses are completely orthogonal. That you can add HKP to get that kind of generics without having any special typeclass syntax.