복붙노트

[SCALA] 엉성한 부산물 패턴 매칭

SCALA

엉성한 부산물 패턴 매칭

나는 볼품의 로서도와 패턴 매칭을 사용할 수 있습니까?

import shapeless.{CNil, :+:}

type ListOrString = List[Int] :+: String :+: CNil

def f(a: ListOrString): Int = a match {
  case 0 :: second :: Nil => second
  case first :: Nil => first
  case Nil => -1
  case string: String => string.toInt
}

그 과정은이 부산물 (Coproduct)으로 박스되기 때문에,하지 작업을 수행합니다.의

패턴 일치 할 수있는 능력을 로서도을 사용하고 유지하는 다른 방법이 있습니까?

해결법

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

    1.당신은 패턴 일치의 INL 및 INR 생성자를 사용할 수 있습니다 :

    당신은 패턴 일치의 INL 및 INR 생성자를 사용할 수 있습니다 :

    import shapeless.{ CNil, Inl, Inr, :+: }
    
    type ListOrString = List[Int] :+: String :+: CNil
    
    def f(a: ListOrString): Int = a match {
      case Inl(0 :: second :: Nil) => second
      case Inl(first :: Nil) => first
      case Inl(Nil) => -1
      case Inr(Inl(string)) => string.toInt
    }
    

    당신이 컴파일러가 일치 철저한-우리는 그런 경우가 일치하는 것이 불가능 것을 알고 있지만, 컴파일러하지 않는 것을 말할 수있을하려는 경우 CNIL의 경우를 처리하기 때문에이 방법은 너무, 적합하지 않습니다 우리는 이런 일을 할 필요가 :

    def f(a: ListOrString): Int = a match {
      case Inl(0 :: second :: Nil) => second
      case Inl(first :: Nil) => first
      case Inl(Nil) => -1
      case Inl(other) => other.sum
      case Inr(Inl(string)) => string.toInt
      case Inr(Inr(_)) => sys.error("Impossible")
    }
    

    또한 개인적으로 단지 INR과 INL 조금 직관적와 부산물의 해당 위치로 이동 찾을 수 있습니다.

    일반적으로이 다형성 함수 값과 부산물을 통해 배하는 것이 좋습니다 :

    object losToInt extends shapeless.Poly1 {
      implicit val atList: Case.Aux[List[Int], Int] = at {
        case 0 :: second :: Nil => second
        case first :: Nil => first
        case Nil => -1
        case other => other.sum
      }
    
      implicit val atString: Case.Aux[String, Int] = at(_.toInt)
    }
    
    def f(a: ListOrString): Int = a.fold(losToInt)
    

    이제 컴파일러는 당신이 불가능한 경우를 처리하지 않고 exhaustivity을 확인합니다.

  2. ==============================

    2.난 그냥 당신의 필요를 위해 잘 작동 할 수 있음을 여기에 볼품에게 끌어 오기 요청을 제출했다. (그냥 끌어 오기 요청하고 수정을 거칠 수있다 또는 거부 ...하지만 기계를 가지고 당신이 유용한 경우 자신의 코드에서 자유롭게 사용합니다.)

    난 그냥 당신의 필요를 위해 잘 작동 할 수 있음을 여기에 볼품에게 끌어 오기 요청을 제출했다. (그냥 끌어 오기 요청하고 수정을 거칠 수있다 또는 거부 ...하지만 기계를 가지고 당신이 유용한 경우 자신의 코드에서 자유롭게 사용합니다.)

    로부터 커밋 메시지 :

    val result = c.foldCases[Double]
                   .atCase(i => math.sqrt(i))
                   .atCase(s => s.length.toDouble)
                   .atCase(b => if (b) 100.0 else -1.0)
    

    귀하의 예를 들어, 당신이 할 수 있습니다 :

      def f(a: ListOrString): Int = a.foldCases[Int]
        .atCase(list => list match {
          case 0 :: second :: Nil => second
          case first :: Nil => first
          case Nil => -1
          case other => other.sum
        })
        .atCase(s => s.toInt)
    
  3. from https://stackoverflow.com/questions/34107849/pattern-matching-with-shapeless-coproduct by cc-by-sa and MIT license