gpt4 book ai didi

scala - 在 Scalaz 中为过滤器返回析取编写 Monoid 的更好方法

转载 作者:行者123 更新时间:2023-12-02 08:23:57 24 4
gpt4 key购买 nike

我正在尝试为 Filter 实现一个幺半群。 (它与 Scalaz 中的 Reader[A, Boolean] 相同)

type Filter[A] = A => Boolean 

实现过滤器最简单的方法是,

implicit def monoidFilter[A] = new Monoid[Filter[A]] {
override def zero: Filter[A] =
a => false
override def append(f1: Filter[A], f2: => Filter[A]): Filter[A] =
a => f1(a) || f2(a)
}

// test
case class User(name: String, city: String)
val users = List(User("Kelly", ".LONDON"), User("John", ".NY"), User("Cark", ".KAW"))

// filtered: List(User(Kelly,.LONDON), User(John,.NY))
(users filter (london |+| ny) size) shouldBe 2

我发现这是Disjunction。现在我们可以在没有 monoidFilter

的情况下 mappend
import Tags._
import syntax.tag._

val london = (u: User) => Disjunction(u.city endsWith(".LONDON"))
val ny = (u: User) => Disjunction(u.city endsWith("NY"))

(users filter { u => (london |+| ny)(u).unwrap }).size shouldBe 2

但是代码在可用性方面变长了。

所以我的问题是,有没有更好的方法来实现monoidFilter?虽然它已经在 Scalaz 中实现,但我还找不到。

最佳答案

Monoid[A => Boolean]

你实际上可以保留原来的别名

type Filter[A] = A => Boolean

如果您特别想要 monoid,您可以轻松构造这样的实例

import scalaz.std.anyVal._
import scalaz.std.function._

implicit def boolMonoid[A] = function1Monoid[A, Boolean](booleanInstance.disjunction)

这将大大简化语法

val london: Filter[User] = _.city endsWith ".LONDON"
val ny: Filter[User] = _.city endsWith "NY"

users filter( london |+| ny)

Rig[A => Boolean]

但如果我是你,我会使用 Rig ( semiring ) 来自 spire library而不是 Monoid

我不知道是否有库可以将 BooleanRig 提升为 Function1 monad,但是手工制作很容易:

import spire.algebra.Rig

implicit def filterRig[A] = new Rig[Filter[A]] {
def plus(x: Filter[A], y: Filter[A]): Filter[A] = v => x(v) || y(v)
def one: Filter[A] = Function.const(true)
def times(x: Filter[A], y: Filter[A]): Filter[A] = v => x(v) && y(v)
def zero: Filter[A] = Function.const(false)
}

或者更通用的版本

import spire.std.boolean._

implicit def applicativeRigU[MX, X](implicit G: Unapply.AuxA[Applicative, MX, X], rig: Rig[X]): Rig[MX] = {
val A: Applicative[G.M] = G.TC
val L: G.M[X] === MX = Leibniz.symm[Nothing, Any, MX, G.M[X]](G.leibniz)
val rigA = new Rig[G.M[X]] {
def plus(x: G.M[X], y: G.M[X]): G.M[X] = A.lift2(rig.plus)(x, y)
def one: G.M[X] = A.point(rig.one)
def times(x: G.M[X], y: G.M[X]): G.M[X] = A.lift2(rig.times)(x, y)
def zero: G.M[X] = A.point(rig.zero)
}

L.subst(rigA)
}

现在你可以添加另一个过滤器

val nameJ: Filter[User] = _.name startsWith "J"

然后运行

import spire.syntax.rig._

users filter (london + ny * nameJ)

关于scala - 在 Scalaz 中为过滤器返回析取编写 Monoid 的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34214213/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com