0

In Idris, types are first-class values:

FooType : (Type, Type)
FooType = (Int, Int)
fst FooType -- Int : Type

I would like to use somehow this feature in Scala so that I can reuse type members over different methods:

class Foo {
  type FooType = (Int, Int)

  def foo : FooType = { ... }
  def bar : Int = { ... } // Here I would like to reuse the first type of FooType (Int)
}

What is the recommended way to accomplish this in Scala?

jarandaf
  • 4,297
  • 6
  • 38
  • 67
  • `FooType` us available for the scope it was defined on. What do you mean by *reuse type members over different methods*? What is preventing you from using `FooType` everywhere needed? – Yuval Itzchakov Jul 26 '16 at 08:58
  • @YuvalItzchakov `FooType` has type `Tuple2[T1,T2]`, I want to be able to define methods based on type members of `FooType`, e.g. "`FooType._1`" (T1) instead of simply `Int` so that my defined types are reused. I am not sure this is possible though. – jarandaf Jul 26 '16 at 09:08
  • Oh, I see. You want `FooType` to be inferred based on members of a class? – Yuval Itzchakov Jul 26 '16 at 09:11
  • @YuvalItzchakov nope, I want to use types for my methods inferred from type member definitions – jarandaf Jul 26 '16 at 09:32
  • You could write `type A = Int`, `type FooType = (A, Int)`, `def bar : A = { ... }` – devkat Jul 26 '16 at 10:00
  • 1
    @devkat this would indeed work, yes. I am hoping for some "sorcery" at type level (e.g. functions that given a type, return another type (not instances)). Please feel free to post your comment as an answer, I might accept it if no other possibility shows up :-) – jarandaf Jul 26 '16 at 10:23
  • @jarandaf I don't know if it's a limitation of the JVM or what, but Scala seems to offer very, very poor support for the sort of thing you are looking for. Treat types as first class values is only supported in extremely shallow ways in Scala. To go beyond it often require enormous amounts of boilerplate code. – ely Aug 31 '18 at 13:23

2 Answers2

1

I think the closest you can get is using a type member:

trait TupleType[T] { type Member = T }

implicit def toTuple[T](a: (T, T)) = new TupleType[T] {}

type FooType = TupleType[Int]

def foo: FooType = (1, 2)
def bar: FooType#Member = 1

Otherwise you could just use a type alias for your tuple member type:

type A = Int
type FooType = (A, A)

def foo: FooType = (1, 2)
def bar: A = 1
devkat
  • 1,624
  • 14
  • 15
0

It is more or less possible if you create the necessary infrastructure yourself. In scala type level functions aren't really first class. They are implemented at the library level with implicits.

scala> :paste
// Entering paste mode (ctrl-D to finish)

sealed trait Deconstruct[T <: (_,_)] { 
  type fst
  type snd

  def fst(t: T): fst
  def snd(t: T): snd
}

object Deconstruct { 
  implicit def mkDeconstruct[A,B] = new Deconstruct[(A,B)] { 
    type fst = A
    type snd = B

    def fst(t: (A,B)): A = t._1
    def snd(t: (A,B)): B = t._2
  }
}

// Exiting paste mode, now interpreting.

defined trait Deconstruct
defined module Deconstruct

scala> type FooType = (Int,Int)
defined type alias FooType

scala> def foo: FooType = (1,2)
foo: (Int, Int)

scala> def bar(implicit d: Deconstruct[FooType]) = d.fst(foo)
bar: (implicit d: Deconstruct[(Int, Int)])d.fst

scala> bar
res0: Int = 1
Jasper-M
  • 14,966
  • 2
  • 26
  • 37