복붙노트

[SCALA] 스칼라에서 foldLeft를 사용하여 카레 함수에 인수리스트를 적용

SCALA

스칼라에서 foldLeft를 사용하여 카레 함수에 인수리스트를 적용

이 스크롤에 공급 된 초기 값은 충분히 카레 함수 인수의 목록에 foldLeft을 수행 할 수 있고, 작업자에 적용하고, 상기리스트는 인수리스트가 함수 (F)에 전달 될?

예를 들어,하자의 말 f를 다음과 같이 정의한다 :

scala> val f = (i: Int, j: Int, k: Int, l: Int) => i+j+k+l
f: (Int, Int, Int, Int) => Int = <function4>

어떤 우리가 물론 직접 사용할 수 있습니다 :

scala> f(1, 2, 3, 4)
res1: Int = 10

또는 카레 한 번에 인수 하나를 적용 :

scala> f.curried
res2: Int => Int => Int => Int => Int = <function1>

scala> f.curried.apply(1).apply(2).apply(3).apply(4)
res3: Int = 10

언뜻보기에이 외모 foldLeft에 대한 작업을 좋아한다.

같은 foldLeft의 모양을 사용하여 적용의 순서를 설명에서 내 첫 번째 시도 :

scala> List(1, 2, 3, 4).foldLeft(f.curried)({ (g, x) => g.apply(x) })

그러나, 다음과 같은 오류가 산출 :

<console>:9: error: type mismatch;
 found   : Int => Int => Int => Int
 required: Int => Int => Int => Int => Int
              List(1, 2, 3, 4).foldLeft(f.curried)({ (g, x) => g.apply(x) })

오류 메시지의 내 독서는 형식 유추가 g에 대한 몇 가지 힌트를해야한다는 것입니다.

나는 잎 모든 것을 찾고 있어요 솔루션은 g의 종류를 제외하고 내 원래의 표현에 수정되지 않은 :

List(1, 2, 3, 4).foldLeft(f.curried)({ (g: ANSWER, x) => g.apply(x) })

내 첫번째 생각은 노동 조합 유형이 여기에 도움이 될 것이라고했다. 그래서 첫 번째 직감에 해당하는 경우, 나는이 문제를 해결하는 데 필요한 기본 기계를 가지고있는 것 같습니다, 카레 - 하워드를 사용하여 조합 유형의 마일 사빈의 유도를 보았다.

그러나 : 나는 "모두 함께 카레 기능 유형 만 제공되는 마지막 인수에 함수의 전체 카레 유형에서 모든 유형의 조합"을 참조 할 수 있다면 노동 조합 유형이 대답하더라도 그것은 도움이 될 것입니다. 즉, 방법은 유형을 설정합니다 :

T1 => ... => Tn

노조 타입으로 :

(T1 => ... => Tn) |∨| ... |∨| (Tn-1 => Tn)

위의 g의 형태로 유용 할 것이다.

목록에 foldLeft을 수행하면 T1은 TN-1을 통해 모두 동일한 경우에 토론을 제한합니다. 와 같은 표기

(T1 =>)+ Tn

내가 g을 제공 할 유형을 설명합니다.

우리가 사용하는 반복자에 경계를 제공 할 수 있도록 내가 대한 부탁 해요 특정 케이스는, 임의의 긴 사슬을 필요로하지 않습니다

(T1 =>){1,4} Tn

모든 접미사의 집합으로 체인을 자르면 유형에 아마도 몇 가지 마법의 기능을하지만,없는 동일 유형의 체인이 작업을 수행하고자에서 미리 보는 것은 더 유용합니다 :

Suffixes(T1 => ... => Tn)

이 구현은 물론 순간에 내 스칼라 능력을 넘어이다. 그렇게 대해 이동하는 방법에 대한 어떤 힌트를 주시면 감사하겠습니다. 이 스칼라의 기존 형식 시스템의 고급 사용 또는 컴파일러 플러그인 또는 둘을 통해 수행 할 수 있는지 여부, 나도 몰라.

같은 "노동 조합 유형"이 사용 사례에 매우 적합하지 않은 결과를 호출, 아래의 코멘트에 주목하고있다. 내가 전화를 다른 어떤 모르겠지만, 그게 내가 지금 가지고있는 가장 가까운 생각입니다. 다른 언어는이 아이디어에 대한 특별 지원이 있습니까? 어떻게 것 COQ 및 AGDA에서이 작품?

모두가 좋은 것입니다하지만이 문제를 명명하고 (등 유형 이론, decidability, 그리고) 더 큰 그림에 대한 앉아 위치를 이해하는 것은, 답변의 작업을 구현하는 것보다 나에게 더 중요하다. 일반적으로 Scalaz, Monoids, 또는 카테고리 이론에 연결을 그릴 수있는 사람에게 보너스 포인트.

해결법

  1. ==============================

    1.아웃이 회전 내가 처음에 예상했던 것보다 꽤 간단합니다.

    아웃이 회전 내가 처음에 예상했던 것보다 꽤 간단합니다.

    먼저 간단한의 HList을 정의해야합니다,

    sealed trait HList
    
    final case class HCons[H, T <: HList](head : H, tail : T) extends HList {
      def ::[H1](h : H1) = HCons(h, this)
      override def toString = head+" :: "+tail.toString
    }
    
    trait HNil extends HList {
      def ::[H1](h : H1) = HCons(h, this)
      override def toString = "HNil"
    }
    
    case object HNil extends HNil
    type ::[H, T <: HList] = HCons[H, T]
    

    그럼 우리가 유도 타입 클래스의 도움으로 우리의 배와 같은 기능을 정의 할 수 있습니다,

    trait FoldCurry[L <: HList, F, Out] {
      def apply(l : L, f : F) : Out
    }
    
    // Base case for HLists of length one
    implicit def foldCurry1[H, Out] = new FoldCurry[H :: HNil, H => Out, Out] {
      def apply(l : H :: HNil, f : H => Out) = f(l.head)
    }
    
    // Case for HLists of length n+1
    implicit def foldCurry2[H, T <: HList, FT, Out]
      (implicit fct : FoldCurry[T, FT, Out]) = new FoldCurry[H :: T, H => FT, Out] {
        def apply(l : H :: T, f : H => FT) = fct(l.tail, f(l.head))
    }
    
    // Public interface ... implemented in terms of type class and instances above
    def foldCurry[L <: HList, F, Out](l : L, f : F)
      (implicit fc : FoldCurry[L, F, Out]) : Out = fc(l, f)
    

    우리는 먼저 원래 예를 들어, 다음과 같이 사용할 수 있습니다

    val f1 = (i : Int, j : Int, k : Int, l : Int) => i+j+k+l
    val f1c = f1.curried
    
    val l1 = 1 :: 2 :: 3 :: 4 :: HNil
    
    // In the REPL ... note the inferred result type
    scala> foldCurry(l1, f1c)
    res0: Int = 10
    

    그리고 우리는 또한, 다른 인수에 대응의와 기능 및 비 균일 인수의 형태에 대해 동일한 수정되지 않은 foldCurry을 사용할 수 있습니다

    val f2 = (i : Int, s : String, d : Double) => (i+1, s.length, d*2)
    val f2c = f2.curried
    
    val l2 = 23 :: "foo" :: 2.0 :: HNil
    
    // In the REPL ... again, note the inferred result type
    scala> foldCurry(l2, f2c)
    res1: (Int, Int, Double) = (24,3,4.0)
    
  2. ==============================

    2.귀하의 기능은 정확히 4 Int 인 인수를 기대하고있다. foldLeft는 임의의 수의 요소에 적용되는 함수이다. 당신은 언급 목록 (1,2,3,4)하지만 당신이있는 경우 목록 (1,2,3,4,5) 또는 목록 ()?

    귀하의 기능은 정확히 4 Int 인 인수를 기대하고있다. foldLeft는 임의의 수의 요소에 적용되는 함수이다. 당신은 언급 목록 (1,2,3,4)하지만 당신이있는 경우 목록 (1,2,3,4,5) 또는 목록 ()?

    List.foldLeft는 [B]는 또한 함수는 동일한 타입 B를 반환 할 것으로 예상되지만 경우 지능 일부 기능 1 [INT, _]는 동일한 타입이다.

    당신도 일반되지 않을 것 가지고 올간에 솔루션입니다. 예를 들어 함수 유형의 어떤 경우 (INT, 플로트, INT, 문자열) => Int 인? 그런 다음 목록 필요 [모든]

    그래서 확실히 List.foldLeft위한 작업이 아니다.

    마음에 (매우 취소 스칼라 코드 경고)두고 :

    class Acc[T](f: Function1[T, _]) {
      private[this] var ff: Any = f
      def apply(t: T): this.type = {
        ff = ff.asInstanceOf[Function1[T,_]](t)
        this
      }
      def get = ff match { 
        case _: Function1[_,_] => sys.error("not enough arguments")
        case res => res.asInstanceOf[T]
      }
    }
    
    List(1,2,3,4).foldLeft(new Acc(f.curried))((acc, i) => acc(i)).get
    // res10: Int = 10
    
  3. ==============================

    3.어떤 scalaz없이 솔루션 만 설명을 확인. 당신이 1로 f.curried.apply를 사용하는 경우 다음 REPL에서 2 인자와는 유형이 실제로마다 다를 반환-결과를 관찰! FoldLeft은 매우 간단합니다. 그것은 f.curried 당신의 시작 인수와 함께 그것의 유형 고정이고 그되지 f.curried.apply (1)과 동일한 서명을 가지고 있기 때문에이 작업을하지 않습니다. 그래서 시작 인수와 결과는 동일한 유형이어야합니다. 타입은 네가 foldLeft의 시작 합 요소 일치한다. 그 절대적으로 작동하지 않을 수 있도록 그리고 당신의 결과도 Int 인 것이다. 도움이 되었기를 바랍니다.

    어떤 scalaz없이 솔루션 만 설명을 확인. 당신이 1로 f.curried.apply를 사용하는 경우 다음 REPL에서 2 인자와는 유형이 실제로마다 다를 반환-결과를 관찰! FoldLeft은 매우 간단합니다. 그것은 f.curried 당신의 시작 인수와 함께 그것의 유형 고정이고 그되지 f.curried.apply (1)과 동일한 서명을 가지고 있기 때문에이 작업을하지 않습니다. 그래서 시작 인수와 결과는 동일한 유형이어야합니다. 타입은 네가 foldLeft의 시작 합 요소 일치한다. 그 절대적으로 작동하지 않을 수 있도록 그리고 당신의 결과도 Int 인 것이다. 도움이 되었기를 바랍니다.

  4. from https://stackoverflow.com/questions/7606587/applying-an-argument-list-to-curried-function-using-foldleft-in-scala by cc-by-sa and MIT license