>

f 함수를 정의하고 싶습니다  다른 함수 g 가 필요합니다 . 우리는 g 가 필요합니다   n 를 가지고  복식 (일부 고정 n 의 경우) ) 및 Double을 반환합니다. 함수 호출 f(g)   n 의 특정 값을 반환해야합니다 .

예 : f(Math.max) = 2  Math.sin은 (Double, Double) => Double 타입을 가지고 있기 때문에 및 f(Math.sin) = 1  Math.sin은 Double => Double 타입을 가지고 있기 때문에 .

f 를 어떻게 정의 할 수 있습니까  스칼라 제네릭을 사용하십니까?

성공하지 못한 여러 형식을 시도했습니다. 예를 들면 다음과 같습니다.

def f[A <: Product](g: Product => Double) = {...}

n 의 값을 추출 할 수 없기 때문에 작동하지 않습니다  컴파일 타임에 A 를 제한 할 수 없습니다   Double 만 포함  값.


  • 답변 # 1

    스프레이 팀이 만든 자석 패턴이라는 패턴이 있습니다. 그것은 당신이 원하는 것을 정확하게 수행합니다.

  • 답변 # 2

    이것은 내가 Shapeless를 들여다보기에 좋은 변명이었습니다.

    $ git clone git@github.com:milessabin/shapeless.git
    ...
    $ cd shapeless
    
    

    (1)

    Shapeless는 arity에 대한 추상화, 특히 이기종 목록 ( HList )으로의 표현을 제공합니다. ). 임의의 arity의 기능은 FnHList 로 볼 수 있습니다  ( HList 를 취하는 함수  논쟁으로).

    $ sbt shapeless-core/console
    scala> import shapeless._
    import shapeless._
    scala> def isFunction[A](fun: A)(implicit fnh: FnHLister[A]) {}
    isFunction: [A](fun: A)(implicit fnh: shapeless.FnHLister[A])Unit
    scala> isFunction(math.sqrt _)
    scala> isFunction(math.random _)
    
    

    (2)

    이제 함수가 Double 를 반환하도록 요구하자 :

    scala> def isFunReturningDouble[A](fun: A)(implicit fnh: FnHLister[A] { type Result = Double }) {}
    isFunReturningDouble: [A](fun: A)(implicit fnh: shapeless.FnHLister[A]{type Result = Double})Unit
    scala> isFunReturningDouble(math.sqrt _)
    scala> isFunReturningDouble(math.signum _)
    <console>:12: error: could not find implicit value for parameter fnh: shapeless.FnHLister[Int => Int]{type Result = Double}
                  isFunReturningDouble(math.signum _)
                                      ^
    
    

    (3)

    와이즈 비즈  type 클래스는 인수 목록의 상한을 볼 수 있습니다.

    LUBConstraint
    
    

    (4)

    이제 우리는 여전히 어떻게 든 arity를 ​​추출해야합니다. 유형 수준에서 이것은 scala> def isValidFun[A, B <: HList](fun: A)(implicit fnh: FnHLister[A] { type Result = Double; type Args = B }, lub: LUBConstraint[B, Double]) {} isValidFun: [A, B <: shapeless.HList](fun: A)(implicit fnh: shapeless.FnHLister[A]{type Result = Double; type Args = B}, implicit lub: shapeless.LUBConstraint[B,Double])Unit scala> isValidFun(math.random _) scala> isValidFun((i: Int) => i.toDouble) <console>:12: error: could not find implicit value for parameter lub: shapeless.LUBConstraint[B,Double] isValidFun((i: Int) => i.toDouble) ^ 입니다.   Length 에 제공되는 . 런타임 값을 얻으려면 다른 유형 클래스 HList  필요합니다.

    최종 기능은 다음과 같습니다.

    ToInt
    
    

    테스트 :

    import shapeless._
    def doubleFunArity[A, B <: HList, C <: Nat](fun: A)(implicit
      fnh: FnHLister[A] { type Result = Double; type Args = B }, 
      lub: LUBConstraint[B, Double],
      len: Length[B] { type Out = C },
      res: ToInt[C]
    ): Int = res()
    
    

    불행히도 많은 scala> doubleFunArity(math.sqrt _) res15: Int = 1 scala> doubleFunArity(math.random _) res16: Int = 0 scala> val g: (Double, Double) => Double = math.max _ g: (Double, Double) => Double = <function2> scala> doubleFunArity(g) res17: Int = 2  작업에 과부하가 걸리고 강력한 유형 제약이 없으면 Scala는 math 를 제공하지 않습니다.  버전은 자동이지만 Double 를 사용합니다  어떤 이유로 든 버전 :

    Int
    
    

    따라서 간접 scala> math.max _ res18: (Int, Int) => Int = <function2> 가 필요합니다  이 작업을 수행합니다.

    <시간>

    구체적인 경우에는 이것이 최선의 방법이라고 말할 수는 없지만 재미있는 탐험이라고 생각합니다.

  • 답변 # 3

    아마도 가장 쉬운 해결책은 오버로드를 다음과 같이 사용하는 것입니다.

    math.max _: ((Double, Double) => Double)
    
    

    (유형 삭제로 인해 런타임에 함수 인수/반환 유형을 확인할 수 없으므로 요구 사항을 충족시키는 완전한 일반 함수를 작성할 수 없다고 생각합니다.)

    def f(g: () => Double) = 0; def f(g: (Double) => Double) = 1; def f(g: (Double, Double) => Double) = 2; def f(g: (Double, Double, Double) => Double) = 2; // ... println(f(Math.pow _)); println(f(Math.sin _));

관련 자료

  • 이전 HTML5를 사용하여 캔버스 내에서 드래그 앤 드롭 기능
  • 다음 javascript - CSS는 이전 형제를 선택합니다