Skip to content

Instantly share code, notes, and snippets.

@JoeyEremondi
Last active February 7, 2018 14:16
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoeyEremondi/26de88df1cadbc5347d9 to your computer and use it in GitHub Desktop.
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
@mgold
Copy link

mgold commented Jan 27, 2016

But doesn't this suffer from the lack of higher-kinded polymorphism? The following isn't valid:

type alias Constant m rest = {rest | constant : b -> m b }

And that's just the beginning if you want to write map, andMap, and andThen.

@JoeyEremondi
Copy link
Author

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.

@Fresheyeball
Copy link

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?

@JoeyEremondi
Copy link
Author

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.

@mgold
Copy link

mgold commented Jan 27, 2016

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.

@Fresheyeball
Copy link

Is the ability to generalize functions over Monads not a sufficient use case?

@mgold
Copy link

mgold commented Jan 27, 2016

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.

@Fresheyeball
Copy link

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.

@rtfeldman
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment