2014-02-09 46 views
9

我想在Scala中使用>=>(Kleisli箭頭)。據我瞭解,它構成了返回monad的函數。現在我試試看如下:如何在Scala中使用> =>?

 
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是monad,但是Some不是。在象Haskell語言Some相當於甚至不是一個類型,它只是一個構造函數,但由於代數數據類型在斯卡拉編碼的方式,你要注意這個問題。有兩個簡單的修復,或者提供明確的更一般的類型:

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> 

或者使用Scalaz的方便some,它返回一個適當類型的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> 

的第二個問題是,>=>不爲斯卡拉茲的普通舊單子功能提供 - 您需要使用Kleisli包裝:

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

這正是你想要的 - 只需使用h.run來解開。

+0

謝謝!很好的解釋:)我不完全明白爲什麼我需要這個'Kleisli'包裝。這僅僅是一些_technicality_還是真正的主要的東西? – Michael

+0

這是一個設計決定 - 你可以肯定地使用一個隱式類來添加'> =>'給任何舊的'A => M [B]'。我可以推測這個決定的原因,但這對斯卡拉茨郵件列表來說是一個更好的問題。 –

相關問題