如何使自己的for-comprehension兼容scala monad?
发布时间:2020-12-16 08:49:49 所属栏目:安全 来源:网络整理
导读:我想在 Scala中实现我自己的for-comprehension兼容的monad和functor. 我们以两个愚蠢的monad为例.一个monad是一个状态monad,包含一个可以映射或平面映射的“Int”. val maybe = IntMonad(5)maybe flatMap( a = 3 * ( a map ( () = 2 * a ) ) )// returns Int
我想在
Scala中实现我自己的for-comprehension兼容的monad和functor.
我们以两个愚蠢的monad为例.一个monad是一个状态monad,包含一个可以映射或平面映射的“Int”. val maybe = IntMonad(5) maybe flatMap( a => 3 * ( a map ( () => 2 * a ) ) ) // returns IntMonad(30) 另一个monad采取像这样的功能组合…… val func = FunctionMonad( () => println("foo") ) val fooBar = func map ( () => println("bar") ) fooBar() // foo // bar // returns Unit 这个例子可能有一些错误,但你明白了. 我希望能够在Scala中使用这两种不同类型的Monad组成的for-understanding.像这样: val myMonad = IntMonad(5) for { a <- myMonad b <- a*2 c <- IntMonad(b*2) } yield c // returns IntMonad(20) 我不是斯卡拉大师,但你明白了 解决方法
对于在for-comprehension中使用的类型,您实际上只需要为它返回返回相同类型实例的map和flatMap方法.从语法上讲,for-comprehension由编译器转换为一系列flatMaps,后跟yield的最终映射.只要这些方法具有适当的签名,它就可以工作.
我不确定你的例子是什么,但这里有一个简单的例子,相当于Option: sealed trait MaybeInt { def map(f: Int => Int): MaybeInt def flatMap(f: Int => MaybeInt): MaybeInt } case class SomeInt(i: Int) extends MaybeInt { def map(f: Int => Int): MaybeInt = SomeInt(f(i)) def flatMap(f: Int => MaybeInt): MaybeInt = f(i) } case object NoInt extends MaybeInt { def map(f: Int => Int): MaybeInt = NoInt def flatMap(f: Int => MaybeInt): MaybeInt = NoInt } 我有两个子类型的共同特征(尽管我可以拥有尽可能多的子类型).常见特征MaybeInt强制每个子类型符合map / flatMap接口. scala> val maybe = SomeInt(1) maybe: SomeInt = SomeInt(1) scala> val no = NoInt no: NoInt.type = NoInt for { a <- maybe b <- no } yield a + b res10: MaybeInt = NoInt for { a <- maybe b <- maybe } yield a + b res12: MaybeInt = SomeInt(2) 此外,您还可以添加foreach和过滤器.如果你想处理这个(没有收益): for(a <- maybe) println(a) 你会添加foreach.如果你想使用if guard: for(a <- maybe if a > 2) yield a 你需要filter或withFilter. 一个完整的例子: sealed trait MaybeInt { self => def map(f: Int => Int): MaybeInt def flatMap(f: Int => MaybeInt): MaybeInt def filter(f: Int => Boolean): MaybeInt def foreach[U](f: Int => U): Unit def withFilter(p: Int => Boolean): WithFilter = new WithFilter(p) // Based on Option#withFilter class WithFilter(p: Int => Boolean) { def map(f: Int => Int): MaybeInt = self filter p map f def flatMap(f: Int => MaybeInt): MaybeInt = self filter p flatMap f def foreach[U](f: Int => U): Unit = self filter p foreach f def withFilter(q: Int => Boolean): WithFilter = new WithFilter(x => p(x) && q(x)) } } case class SomeInt(i: Int) extends MaybeInt { def map(f: Int => Int): MaybeInt = SomeInt(f(i)) def flatMap(f: Int => MaybeInt): MaybeInt = f(i) def filter(f: Int => Boolean): MaybeInt = if(f(i)) this else NoInt def foreach[U](f: Int => U): Unit = f(i) } case object NoInt extends MaybeInt { def map(f: Int => Int): MaybeInt = NoInt def flatMap(f: Int => MaybeInt): MaybeInt = NoInt def filter(f: Int => Boolean): MaybeInt = NoInt def foreach[U](f: Int => U): Unit = () } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容