Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: how to work with long type parameter lists

What techniques can I use in Scala to deal with long type parameter lists?

I am working on a little framework for running various types of games with different simulated environments. I am trying to keep certain parts of the framework relatively generic, so I am introducing various types as type parameters, such as the state of the environment, the game result, etc.

It all works quite well functionally and I do get the desired benefits of a type-safe yet generic framework. But the type signatures have grown to the point where it makes the code rather hard to read and refactoring it has become quite cumbersome. The signature of the top-level Simulator has eight type parameters and many of the primary types have three to five. Individual compiler type errors, since they list out the types of class or function parameters (which of course are also type-parameterized) seem to regularly run to a hundred lines.

Occasionally, but very rarely, I can omit the type parameters, e.g. on constructors. But in most cases at least one of the types wont be inferred so I end up having to insert the entire type signature.

Obviously this is not ideal and I am looking for ways to solve this problem. Any advice would be appreciated!

like image 901
Gregor Scheidt Avatar asked Feb 12 '12 07:02

Gregor Scheidt


1 Answers

Two solutions come to mind.

  1. Use type aliases.

    scala> class Foo[A, B, C, D, E]
    defined class Foo
    
    scala> type Bar[A] = Foo[A, Int, Int, Int, Float]
    defined type alias Bar
    
    scala> new Bar[String]
    res23: Foo[String,Int,Int,Int,Float] = Foo@f590c6
    
  2. Use abstract type members instead of type parameters.

    scala> class Bar {
         |   type A
         |   type B <: AnyVal
         |   type C
         | }
    defined class Bar
    
    scala> new Bar {
         |   type A = String
         |   type B = Int
         |   type C = Int
         | }
    res24: Bar{type A = String; type B = Int; type C = Int} = $anon$1@ee1793
    
    scala> trait Baz {
         |   type A = String
         | }
    defined trait Baz
    
    scala> new Bar with Baz {
         |   type B = Int
         |   type C = String
         | }
    res25: Bar with Baz{type B = Int; type C = String} = $anon$1@177c306
    
    scala> null.asInstanceOf[res25.A]
    res26: res25.A = null
    
    scala> implicitly[res25.A =:= String]
    res27: =:=[res25.A,String] = <function1>
    

You might want to share some code with us so that we can give some more specific advice.

like image 180
missingfaktor Avatar answered Nov 11 '22 20:11

missingfaktor