Skip to content

Instantly share code, notes, and snippets.

@missingfaktor
Created March 31, 2012 17:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save missingfaktor/2266798 to your computer and use it in GitHub Desktop.
Save missingfaktor/2266798 to your computer and use it in GitHub Desktop.
scala> trait TF {
| type ![A]
| }
defined trait TF
scala> type Curried2[F[_, _]] = TF {
| type ![X] = TF {
| type ![Y] = F[X, Y]
| }
| }
defined type alias Curried2
scala> "a".pure[Curried2[State] # ![Int] # !]
res0: scalaz.State[Int,java.lang.String] = scalaz.States$$anon$1@6e375e
@mergeconflict
Copy link

Interesting... How about just:

scala> type Curried2[F[_, _]] = {
     |   type ![A] = {
     |     type ![B] = F[A, B]
     |   }
     | }

@missingfaktor
Copy link
Author

@mergeconflict: Oh yes, TF isn't necessary. Thanks!

@mergeconflict
Copy link

Could even go further:

scala> type ![F[_, _], A] = { type ![B] = F[A, B] }
defined type alias $bang

scala> "a".pure[(State ! Int) # !]
res0: scalaz.State[Int,java.lang.String] = scalaz.States$$anon$1@6e375e

... but I'm not sure I prefer this to my idea.

@missingfaktor
Copy link
Author

I wouldn't use this one because when scaled up, the syntax won't look the same for higher arities. The approach proposed in the original gist does not have this problem.

I am not sure what your proposed solution (on marakana post) buys. You are still using type lambda there. The value level equivalents would be:
g(x => foo(bar(x))) changed to val f = x => foo(bar(x)); g(f)

@mergeconflict
Copy link

True, the (State ! Int) # ! thing is just an idea I had for an arity-2 shortcut. Yours is definitely more general.

My solution does still have the type lambda in there; the only thing I'm doing is giving it an interesting name within the scope it applies to. I think our ideas both complement each other... We could have:

def stateMonad[S] = {
  type `State[S]` = Curried2[State] # ![S] # !
  new Monad[`State[S]`] { ... }
}

@mergeconflict
Copy link

By the way, somebody's probably pointed this out before but couldn't there be some nice symmetry between infix/postfix notation for values (omitting dots) and for types (omitting hashes):

x.foo(a).bar   <-->   X#Foo[A]#Bar
x foo a bar    <-->   X Foo A Bar  ???

That would make your Curried2 thing neater: Curried2[State] ! S !

@missingfaktor
Copy link
Author

Yes, the complement-version indeed looks nicer.

As for A B C syntax, it already means B[A, C].

@mergeconflict
Copy link

D'oh, of course.

@mergeconflict
Copy link

Okay, how about this craziness:

scala> type ![F <: { type !![_] }, A] = F # !![A]
defined type alias $bang

scala> type Curried2[F[_, _]] = {
     |   type !![A] = {
     |     type !![B] = F[A, B]
     |   }
     | }
defined type alias Curried2

scala> type LookNoHashes[A] = Curried2[State] ! Int ! A
defined type alias LookNoHashes

:)

@missingfaktor
Copy link
Author

I can't say I wasn't anticipating this. ;-)

@mergeconflict
Copy link

Note: I'm a moron.

def stateMonad[S] = {
  type `State[S]`[A] = State[S, A]
  new Monad[`State[S]`] { ... }
}

Duh... No need for the type lambda trick here at all. Or rather, since we have our enclosing scope with S defined, we're sort of "inside" the type lambda already.

@missingfaktor
Copy link
Author

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