[SCALA] 스칼라에서 FORALL
SCALA스칼라에서 FORALL
하스켈에서, 아래와 같이, 그것은 그들에 특정 상황에 맞는 범위와 유형이 유형 목록의 값을 저장하는 것이 가능하다 :
data ShowBox = forall s. Show s => ShowBox s
heteroList :: [ShowBox]
heteroList = [ShowBox (), ShowBox 5, ShowBox True]
어떻게 바람직하게는 하위 유형하지 않고, 스칼라에서 동일한을 달성 할 수 있습니까?
해결법
-
==============================
1.@Michael 콜이 주석으로 하스켈 FORALL의 사용은 존재 형태이고 정확히 forSome 구조체 또는 와일드 카드를 사용하여 스칼라 replicted 수있다. 즉, @ 패러다임의 대답은 크게 올바른지.
@Michael 콜이 주석으로 하스켈 FORALL의 사용은 존재 형태이고 정확히 forSome 구조체 또는 와일드 카드를 사용하여 스칼라 replicted 수있다. 즉, @ 패러다임의 대답은 크게 올바른지.
그럼에도 불구하고 그 쇼박스 유형의 인스턴스는 정확한 기본 유형이 존재 적 밖으로 정량화 된 경우에도 목록 요소에 사용하기에 사용할 수 있도록하는 방식으로 해당 표시 유형 클래스 인스턴스를 캡처 할 수있는 하스켈 원본이 상대적으로없는 뭔가가있다 . @ 패러다임의 대답에 귀하의 의견은 다음과 같은 하스켈에 뭔가 상당을 쓸 수 있도록 할 것을 제안
data ShowBox = forall s. Show s => ShowBox s heteroList :: [ShowBox] heteroList = [ShowBox (), ShowBox 5, ShowBox True] useShowBox :: ShowBox -> String useShowBox (ShowBox s) = show s -- Then in ghci ... *Main> map useShowBox heteroList ["()","5","True"]
@Kim Stebel의 대답 쇼 하위 유형을 이용하여 객체 지향 언어에서 그 일을의 표준 방법입니다. 다른 일들이 스칼라에 갈 수있는 올바른 방법이다 즉, 동일한 것. 난 당신이 알고 확신과 하위 유형 피하고 스칼라에서 하스켈의 타입 클래스 기반의 접근 방식을 복제하고자하는 좋은 이유가있다. 여기 간다 ...
단위, 지능 및 BOOL에 대한 표시 유형 클래스 인스턴스 위의 하스켈의 useShowBox 기능의 구현에 사용할 수 있습니다. 우리가 직접 스칼라로이 번역하려고하면 우리는 같은 것을 얻을 것이다
trait Show[T] { def show(t : T) : String } // Show instance for Unit implicit object ShowUnit extends Show[Unit] { def show(u : Unit) : String = u.toString } // Show instance for Int implicit object ShowInt extends Show[Int] { def show(i : Int) : String = i.toString } // Show instance for Boolean implicit object ShowBoolean extends Show[Boolean] { def show(b : Boolean) : String = b.toString } case class ShowBox[T: Show](t:T) def useShowBox[T](sb : ShowBox[T]) = sb match { case ShowBox(t) => implicitly[Show[T]].show(t) // error here ^^^^^^^^^^^^^^^^^^^ } val heteroList: List[ShowBox[_]] = List(ShowBox(()), ShowBox(5), ShowBox(true)) heteroList map useShowBox
이것은 다음과 같이 useShowBox에서 컴파일에 실패,
<console>:14: error: could not find implicit value for parameter e: Show[T] case ShowBox(t) => implicitly[Show[T]].show(t) ^
여기서 문제는 하스켈의 경우와는 달리, 표시 형식의 클래스 인스턴스가 useShowBox 함수의 몸에 쇼박스 인수에서 전파되지, 따라서 사용할 수 없습니다되어 있다는 점이다. 우리가 useShowBox 기능에 바인딩 추가 컨텍스트를 추가하여 그 문제를 해결하려고하면,
def useShowBox[T : Show](sb : ShowBox[T]) = sb match { case ShowBox(t) => implicitly[Show[T]].show(t) // Now compiles ... }
useShowBox 내에서이 수정 문제를,하지만 지금 우리는 우리의 존재 적 정량화 목록에지도와 함께 사용할 수 없습니다,
scala> heteroList map useShowBox <console>:21: error: could not find implicit value for evidence parameter of type Show[T] heteroList map useShowBox ^
useShowBox이지도 함수에 인수로 제공 될 때 우리는 우리가 그 시점에서이 유형의 정보를 기반으로 표시 인스턴스를 선택해야하기 때문이다. 분명히이 목록의 모든 요소에 대한 작업을하고 이것이 우리가 상관 후있을 것이다에 대한 표시 인스턴스를 정의했다면 (컴파일에 실패하지만, 그래서 우리가있어 게 아니에요 것 하나 개 쇼 인스턴스가없는 후 여기에 ... 우리는) 각 목록 요소의 가장 구체적인 유형에 따라 유형 클래스의 인스턴스를 선택합니다.
이 하스켈에서하는 것과 같은 방식으로 작업이를 얻으려면, 우리는 명시 적으로 useShowBox의 신체 내에서 표시 인스턴스를 전달해야합니다. 즉, 다음과 같이 갈 수도
case class ShowBox[T](t:T)(implicit val showInst : Show[T]) val heteroList: List[ShowBox[_]] = List(ShowBox(()), ShowBox(5), ShowBox(true)) def useShowBox(sb : ShowBox[_]) = sb match { case sb@ShowBox(t) => sb.showInst.show(t) }
다음 REPL에서,
scala> heteroList map useShowBox res7: List[String] = List((), 5, true)
우리는 우리가 포함 된 값에 대한 표시 인스턴스에 대한 명시 적 이름 (showInst)을 가질 수 있도록 쇼박스에 바인딩 컨텍스트를 desugared 적이 있습니다. 그런 다음 useShowBox의 몸에서 우리는 명시 적으로 적용 할 수 있습니다. 또한 패턴 일치는 우리가 단지 함수의 본문에 일단 실존 형식을 열 수 있도록하는 것이 필수적입니다 있습니다.
명백해야한다,이 훨씬 더 동등한 하스켈보다 vebose이며, 특별히 다른 매우 좋은 이유가 없다면 난 강력 스칼라의 하위 유형 기반 솔루션을 사용하는 것이 좋습니다 것입니다.
편집하다
주석에서 지적 된 바와 같이, 스칼라 쇼박스의 정의는 상기 하스켈 원래 존재하지 않는 표시 형식의 파라미터를 갖는다. 나는 우리가 사용하는 추상적 인 유형을 해결할 수있는 방법을 볼 사실은 꽤 유익 생각합니다.
먼저 우리는 추상 형식의 멤버 형식 매개 변수를 교체하고 추상적 인 발스와 생성자의 매개 변수를 교체
trait ShowBox { type T val t : T val showInst : Show[T] }
우리는 지금, 사례 클래스 달리 무료로 우리에게 줄 것이라는 팩토리 메소드를 추가해야
object ShowBox { def apply[T0 : Show](t0 : T0) = new ShowBox { type T = T0 val t = t0 val showInst = implicitly[Show[T]] } }
우리는 지금 우리가 이전에 쇼박스 [_]를 사용하는 곳 일반 쇼박스을 사용할 수 있습니다 ... 추상 유형의 멤버가 지금 우리의 존재 한정사의 역할을하고있다,
val heteroList: List[ShowBox] = List(ShowBox(()), ShowBox(5), ShowBox(true)) def useShowBox(sb : ShowBox) = { import sb._ showInst.show(t) } heteroList map useShowBox
(그것의 가치는 스칼라에서 명시 적 포섬의 도입과 와일드 카드로 그 이전에 이것은 당신이 존재 유형을 나타내는 것입니다 방법을 정확하게했다 지적.)
원래 하스켈에서와 같이 우리는 지금 정확히 같은 장소에 존재 있습니다. 나는 이것이 당신이 스칼라에서 얻을 수있는 충실한 연주에 가까운 생각합니다.
-
==============================
2.당신이 준 쇼박스의 예는 실존 유형을 포함한다. 나는 유형 구별하기 위해 SB에 쇼박스 데이터 생성자의 이름을 변경하고 있습니다 :
당신이 준 쇼박스의 예는 실존 유형을 포함한다. 나는 유형 구별하기 위해 SB에 쇼박스 데이터 생성자의 이름을 변경하고 있습니다 :
data ShowBox = forall s. Show s => SB s
우리는의는 "존재"라고하지만, 여기에 FORALL은 보편적 인 정량하고있는 SB 데이터 생성자에 관한 것이다. 우리가 켜져 명시 적 FORALL와 SB 생성자의 종류를 요청하는 경우이 훨씬 명확하게 :
SB :: forall s. Show s => s -> ShowBox
즉, 쇼박스 실제로 세 가지로 구성되어 있습니다 :
유형 (S)가 구성 쇼박스의 일부가되므로, 그것은 실존 정량화된다. 하스켈이 존재 정량 구문을 지원하는 경우, 우리는 타입 별칭으로 쇼박스를 작성할 수 :
type ShowBox = exists s. Show s => s
스칼라는 존재 정량의이 종류를 지원하지 않습니다와 마일의 대답은 위의 바로 그 세 가지로 구성 특성을 사용하여 세부 사항을 제공합니다. 이 "스칼라의 FORALL"에 대한 질문이기 때문에 그러나, 하스켈이하는 것처럼의 정확히 그것을 할 수 있습니다.
스칼라의 데이터 생성자는 명시 적으로 FORALL로 정량화 할 수 없습니다. 그러나, 모듈의 모든 방법 일 수있다. 그래서 당신은 효과적으로 보편적 인 정량화와 같은 유형의 생성자 다형성을 사용할 수 있습니다. 예:
trait Forall[F[_]] { def apply[A]: F[A] }
어떤 주어진 F 스칼라 형 FORALL [F]를하는 FORALL 하스켈 타입 후 동일하다. F의가.
우리는 형식 인수에 제약 조건을 추가하려면이 기술을 사용할 수 있습니다.
trait SuchThat[F[_], G[_]] { def apply[A:G]: F[A] }
유형 F SuchThat G의 값은 FORALL 하스켈 타입의 값과 같다. G A =>은 F. 만약 존재한다면 G [A]의 예는 암시 스칼라에 의해 조회된다.
이제, 우리는 당신의 쇼박스를 인코딩하려면이 옵션을 사용할 수 있습니다 ...
import scalaz._; import Scalaz._ // to get the Show typeclass and instances type ShowUnbox[A] = ({type f[S] = S => A})#f SuchThat Show sealed trait ShowBox { def apply[B](f: ShowUnbox[B]): B } object ShowBox { def apply[S: Show](s: => S): ShowBox = new ShowBox { def apply[B](f: ShowUnbox[B]) = f[S].apply(s) } def unapply(b: ShowBox): Option[String] = b(new ShowUnbox[Option[String]] { def apply[S:Show] = s => some(s.shows) }) } val heteroList: List[ShowBox] = List(ShowBox(()), ShowBox(5), ShowBox(true))
ShowBox.apply 방법은 보편적으로 정량 데이터 생성자이다. 당신은 그냥 하스켈 버전과 같은 타입 S, 쇼의 인스턴스 [S], 및 타입 S의 값을 취하는 것을 볼 수 있습니다.
다음은 사용 예는 다음과 같습니다
scala> heteroList map { case ShowBox(x) => x } res6: List[String] = List((), 5, true)
스칼라에서 더 직접 인코딩이 경우 클래스를 사용할 수 있습니다 :
sealed trait ShowBox case class SB[S:Show](s: S) extends ShowBox { override def toString = Show[S].shows(s) }
그때:
scala> val heteroList = List(ShowBox(()), ShowBox(5), ShowBox(true)) heteroList: List[ShowBox] = List((), 5, true)
이 경우, 목록 [쇼박스는] 목록 [문자열] 기본적으로 동일하지만 좀 더 흥미로운 무언가를 얻기 위해 표시 이외의 특성과이 기술을 사용할 수 있습니다.
이 모든 Scalaz에서 표시 typeclass을 사용하고 있습니다.
-
==============================
3.나는 스칼라 하스켈에서 1 대 1 번역 여기에 가능하다고 생각하지 않습니다. 그런데 왜 당신은 하위 유형을 사용하지 않으려는? 당신이 사용에 (int와 같은) 원하는 종류의 쇼 방법이 부족한 경우에도 암시 적 변환을 통해이를 추가 할 수 있습니다.
나는 스칼라 하스켈에서 1 대 1 번역 여기에 가능하다고 생각하지 않습니다. 그런데 왜 당신은 하위 유형을 사용하지 않으려는? 당신이 사용에 (int와 같은) 원하는 종류의 쇼 방법이 부족한 경우에도 암시 적 변환을 통해이를 추가 할 수 있습니다.
scala> trait Showable { def show:String } defined trait Showable scala> implicit def showableInt(i:Int) = new Showable{ def show = i.toString } showableInt: (i: Int)java.lang.Object with Showable scala> val l:List[Showable] = 1::Nil l: List[Showable] = List($anon$1@179c0a7) scala> l.map(_.show) res0: List[String] = List(1)
-
==============================
4.(편집 : 응답 코멘트에, 쇼 방법을 추가.)
(편집 : 응답 코멘트에, 쇼 방법을 추가.)
난 당신이 같은 컨텍스트 경계를 가지는 암시 적 방법을 사용하여 얻을 수 있다고 생각합니다 :
trait Show[T] { def apply(t:T): String } implicit object ShowInt extends Show[Int] { def apply(t:Int) = "Int("+t+")" } implicit object ShowBoolean extends Show[Boolean] { def apply(t:Boolean) = "Boolean("+t+")" } case class ShowBox[T: Show](t:T) { def show = implicitly[Show[T]].apply(t) } implicit def box[T: Show]( t: T ) = new ShowBox(t) val lst: List[ShowBox[_]] = List( 2, true ) println( lst ) // => List(ShowBox(2), ShowBox(true)) val lst2 = lst.map( _.show ) println( lst2 ) // => List(Int(2), Boolean(true))
-
==============================
5.왜 :
왜 :
trait ShowBox { def show: String } object ShowBox { def apply[s](x: s)(implicit i: Show[s]): ShowBox = new ShowBox { override def show: String = i.show(x) } }
당국 '대답 제안으로, 나는 종종 스칼라은 매우 간단 하나에 "하스켈 타입의 몬스터"를 번역 할 수 있음을 놀라게하고있다.
from https://stackoverflow.com/questions/7213676/forall-in-scala by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] scala.concurrent.blocking - 실제로 무엇을합니까? (0) | 2019.11.14 |
---|---|
[SCALA] 패키지 오브젝트 (0) | 2019.11.14 |
[SCALA] 몇 가지 선물을 기다리는 방법 (0) | 2019.11.14 |
[SCALA] 어떻게 RDD의 내용을 인쇄하려면? (0) | 2019.11.14 |
[SCALA] 어떻게 스칼라를 사용하여 아파치 스파크에 PostgreSQL 데이터베이스에 연결할 수 있습니까? (0) | 2019.11.14 |