如何在Scala中使用> =>?

Mic*_*ael 9 scala scalaz kleisli

我想>=>在Scala中使用(Kleisli箭头).据我所知,它组成了返回monad的函数.现在我尝试如下:

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搭配>=>

Tra*_*own 11

这里有两个问题.首先,您推断的函数类型过于具体.Option是单子,但Some不是.在像Haskell这样的语言中,相当于Some甚至不是一个类型 - 它只是一个构造函数 - 但是由于代数数据类型在Scala中编码的方式,你必须注意这个问题.有两个简单的修复 - 要么明确提供更一般的类型:

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>
Run Code Online (Sandbox Code Playgroud)

或者使用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>
Run Code Online (Sandbox Code Playgroud)

第二个问题是>=>Scalaz中没有提供普通的旧monadic函数 - 你需要使用Kleisli包装器:

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

这正是你想要的 - 只是h.run用来解开.