如何使用> =>在斯卡拉?

时间:2014-02-09 14:50:33

标签: 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
                 ^

为什么不编译?如何使用f撰写g>=>

1 个答案:

答案 0 :(得分:11)

这里有两个问题。首先,您推断的函数类型过于具体。 Option是monad,但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>

或者使用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>

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

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

这完全符合您的要求 - 只需使用h.run来解包。