Is there any comprehensive tutorial on how to use this kind of structural typing?
Asked Answered
M

1

5

As seen here, map is defined

in a slightly funky way

For completeness' sake, here's the code:

implicit def FunctionFunctor[R] = new Functor[({type l[a] = R=>a})#l] {
  def map[A, B](fa: R => A)(f: A => B) : R => B = (x => f(fa(x)))
}

More concretely - new Functor[({type l[a] = R=>a})#l]

I do think I know what's going on, but can't say honestly that I fully understand the concept. And since there is no any hint, I can't event google the term (I simply don't know that to google). Does some tutorial (or review, or whatever) exist where this is explained with a better level of detalization? I'd appreciate even more is someone could explain it right here in the answers.

Masturbate answered 22/7, 2014 at 20:55 Comment(0)
F
8

This is a special case of structural typing but called a 'type lambda', if you search for type lambda scala google will give you some results.

In short, it's used in a similar fashion as partially applied functions.

def x(a:Int, b:Int):Int = a * b
val x10 = x(10, _:Int)
x10(2) // 2

An example with types.

type IntEither[B] = Either[Int, B]
val y:IntEither[String] // Either[Int, String]

In some cases methods or classes expect a type with a single parameter

class Test[F[_]]

You can not give the Test class an Either because Test expects a type with 1 parameter and Either has 2. In order to be able to pass in an Either we can partially apply it

type X[B] = Either[Int, B]
new Test[X]

An alternative way of writing it is like this:

type X = {
  type T[x] = Either[Int, x]
}

new Test[X#T]

Instead of creating a type alias, we can also define the X type anonymously

new Test[({type T[x] = Either[Int, x]})#T]

These all give you an instance of type Test[Either[Int, x]].


Edit

Your example could look like this:

type PartiallyTypedFunction[R] = {
  type T[x] = R => x 
}

implicit def FunctionFunctor[R] =
  new Functor[PartiallyTypedFunction[R]#T] {
    def map[A, B](fa: R => A)(f: A => B): R => B = (x => f(fa(x)))
  }
Femmine answered 22/7, 2014 at 21:26 Comment(3)
Indeed, it looks way too complicated. That's why I usually create a type alias or even a trait or a class to prevent using that horrible syntax.Femmine
@cdshines I've added an example of the code you posted using a type alias.Femmine
Thank you. As about now this looks like the most comprehensive post on all the internetz concerning the subject:)Masturbate

© 2022 - 2024 — McMap. All rights reserved.