여기에는 두 가지 문제가 있습니다. 첫 번째는 추론 된 함수 유형이 너무 구체적이라는 것입니다. 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합니다.
고마워요! 위대한 설명 :) 나는 왜이'Kleisli' 래퍼가 필요한지 완전히 이해하지 못합니다. 그것은 단지 기술적 인 것인가 아니면 정말로 중요한 것입니까? – Michael
이것은 설계상의 결정입니다. 이전의'A => M [B]'에'> =>'을 추가하기 위해 반드시 암시 적 클래스를 사용할 수 있습니다. 나는 그 결정에 대한 이유를 추측 할 수 있지만 Scalaz 메일 링리스트에 대해서는 더 좋은 질문이다. –