2014-02-09 3 views
9

스칼라에서 >=> (Kleisli 화살표)을 사용하려고합니다. 내가 이해하는 한, 모나드를 반환하는 함수를 구성합니다. 이제 다음과 같이 시도합니다 :스칼라에서> => 사용하는 방법?

 
scala> val f = {i:Int => Some(i + 1)} 
f: Int => Some[Int] = <function1> 

scala> val g = {i:Int => Some(i.toString)} 
g: Int => Some[String] = <function1> 

scala> val h = f >=> g 
<console>:15: error: value >=> is not a member of Int => Some[Int] 
     val h = f >=> g 
       ^

왜 컴파일되지 않습니까? fg>=>으로 작성하는 방법은 무엇입니까?

답변

10

여기에는 두 가지 문제가 있습니다. 첫 번째는 추론 된 함수 유형이 너무 구체적이라는 것입니다. Option은 모나드이지만 Some은 아닙니다. Haskell과 같은 언어에서 Some과 같은 것은 타입이 아닙니다. 이것은 단지 생성자입니다. 그러나 대수 데이터 유형이 스칼라로 인코딩되는 방식 때문에이 문제를 조심해야합니다. 두 쉽게 수정-중 하나가 있습니다 명시 적으로 더 일반적인 유형 제공 : 두 번째 문제는 >=>이되지 않는 것입니다

scala> val f = (i: Int) => some(i + 1) 
f: Int => Option[Int] = <function1> 

scala> val g = (i: Int) => some(i.toString) 
g: Int => Option[String] = <function1> 

:

scala> val f: Int => Option[Int] = i => Some(i + 1) 
f: Int => Option[Int] = <function1> 

scala> val g: Int => Option[String] = i => Some(i.toString) 
g: Int => Option[String] = <function1> 

를 그대로 사용하거나 적절 Some를 입력 반환 Scalaz의 편리한 some, Scalaz의 일반 모나드 함수에 제공됩니다. Kleisli 래퍼를 사용해야합니다.

scala> val h = Kleisli(f) >=> Kleisli(g) 
h: scalaz.Kleisli[Option,Int,String] = Kleisli(<function1>) 

이것은 정확히 원하는 것을 수행합니다. h.run을 사용하여 unwrap합니다.

+0

고마워요! 위대한 설명 :) 나는 왜이'Kleisli' 래퍼가 필요한지 완전히 이해하지 못합니다. 그것은 단지 기술적 인 것인가 아니면 정말로 중요한 것입니까? – Michael

+0

이것은 설계상의 결정입니다. 이전의'A => M [B]'에'> =>'을 추가하기 위해 반드시 암시 적 클래스를 사용할 수 있습니다. 나는 그 결정에 대한 이유를 추측 할 수 있지만 Scalaz 메일 링리스트에 대해서는 더 좋은 질문이다. –