2016-09-21 2 views
3

형태없는 문서에서는 다형성 함수를 사용하여 한 종류의 컨테이너에있는 객체를 다른 컨테이너에 매핑하는 함수를 만드는 방법을 설명하지만 컨테이너에서 객체의 압축을 해제 할 때는 어떻게해야합니까?다형 함수를 사용하여 옵션에서 객체 추출

은 내가 각 옵션의 내용을 추출 할 수있는 다형성 기능을 원하는 옵션

val options = Some(1) :: Some("A") :: Some(3.5) :: HNil 

의 HList 있습니다. 내 다형성 함수가 실제로 작동하도록

options.map(uuu) // I want: 1 :: "A" :: 3.5 :: HNil 

가 어떻게이 문제를 해결 할 수 있습니다 :이 기능이 정확하면

// This is incorrect: 
object uuu extends (Option ~> Any) { 
    def apply[T](l:Option[T]):T = { 
    l.get 
    } 
} 

, 나는 다음과 같은 동작을 싶어?

답변

2

여기에 몇 가지 문제가 있습니다. 첫 번째는 hlist의 정적 유형에 Option 대신 Some이 있으므로 uuuoptions에 매핑 될 수 있음을 증명해야한다는 증거가 Mapper임을 알 수 없습니다. 이 문제를 해결하는 가장 좋은 방법은 반환하는 스마트 Some 생성자를 정의하는 것입니다 Option :

def some[A](a: A): Option[A] = Some(a) 

val options = some(1) :: some("A") :: some(3.5) :: HNil 

또한 원래 options에 유형 주석을 추가하거나 Some 대신 Option 작업을 uuu을 변경할 수 있습니다 (이 될 것입니다 더 안전하지만 아마도 목표가 무엇이든간에 덜 유용 할 것입니다.)

이제 코드가 으로 컴파일되지만, 이는 Any이 스칼라에서 kind-polymorphic이라는 다소 기괴한 사실 때문입니다. 일반적으로 F ~> G이있는 경우 FG은 단일 유형 매개 변수를 취하는 유형 생성자 여야합니다 (예 : Option ~> List. Any은 형식 매개 변수를 사용하지 않고 작동하지만 스칼라 언어에 대한 이상한 사실 (AnyNothing과 함께 kind-polymorphic이며 형식이 필요한 슬롯, 형식 생성자와 하나의 매개 변수, 12 개의 매개 변수가있는 유형 생성자 등).

그래야 컴파일됩니다.하지만 Any :: Any :: Any :: HNil을 반환하기 때문에 꽤 쓸모가 없습니다. 당신은 shapeless.Id과 자연의 변화에 ​​Any을 대체하여이 문제를 해결할 수 있습니다

import shapeless._, shapeless.poly.~> 

def some[A](a: A): Option[A] = Some(a) 

val options = some(1) :: some("A") :: some(3.5) :: HNil 

object uuu extends (Option ~> Id) { 
    def apply[T](l: Option[T]): T = l.get 
} 

options.map(uuu) 

Idtype Id[+T] = T -i.e.으로 정의된다, 그것은 당신에게 풀어 유형을 제공 신원 타입 생성자입니다.

모두 컴파일이 버전은 다시 유용하게 형식의 결과를 제공하지만, 당신이 (런타임) None 있습니다와 hlist 오버 요소를하게되면, 이후는, 당신이 NoSuchElementException를 얻을 수 있습니다, 아직 정말 안전하지. 이 문제를 해결하기위한 방법이 전혀 없습니다. Option ~> Id에서 Some ~> Id으로 어떻게 든 기본값을 제공하는 등 운영의 성격이 크게 바뀝니다.

+0

트래비스는 '스칼라에서 어떤 종류의 다형성이 있습니까?' –

+0

@KevinMeredith 글쎄, 그 단락은 기초를 설명합니다.좀 더 구체적으로'def foo [F [_, _, _]] (f : F [Int, Int, Int]) = f'을 정의하고'foo [Any] (1)'를 시도하십시오. –

관련 문제