Simulate partial type parameter inference with implicits?

后端 未结 2 1419
-上瘾入骨i
-上瘾入骨i 2021-01-06 07:41

I\'m making a simple dependency injection framework, for constructor injection, in Scala. The idea is that objects that are DI\'d put their required services in their constr

相关标签:
2条回答
  • 2021-01-06 08:11
    trait Construct[T, A] {
     def apply(arg: A): T
    }
    
    class Constructor[T]{
      def apply[A](arg : A)(implicit construct : Construct) = construct(arg)
    }
    
    object Constructor {
     def apply[T] = new Constructor[T]
    }
    
    Constructor[T]("arg")
    
    0 讨论(0)
  • 2021-01-06 08:31

    Type parameter inference in Scala is an all or nothing affair: if you explicitly supply any of the type arguments for a type parameter block then you must supply them all. Consequently, if you want to supply only some of a set of type arguments you must arrange for them to belong to separate type parameter blocks.

    The way to do that in this case is to split the construct method into two stages: the first, which takes an explicit type argument and returns a function-like value; and a second, which applies the function-like value to the arguments for which you want the types to be inferred.

    Here's how it might go,

    // Function-like type
    class Construct1[T] {
      def apply[A](arg1: A)(implicit ctor : Constructor1[T, A]): T =
        ctor.construct(arg1)
    }
    
    def construct[T] = new Construct1[T]
    

    The result of invoking construct[Foo] is a value of type Construct1[Foo]. This has an apply method with a type parameter, which can be inferred, and an implicit parameter whose type is determined by both T and A. The invocation you want to make now looks like,

    construct[Foo].apply("asd")  // T explicit, A inferred as String
    

    Scala's semantic sugaring rules around apply applies here which mean that this can be rewritten as,

    construct[Foo]("asd")
    

    which is exactly the result you want.

    0 讨论(0)
提交回复
热议问题