我已经写了两个无标签代数,我想为其中一个写定律。
代数如下:
@newtype case class Variable(v: String)
@newtype case class Value(v: String)
trait Environment[F[_]] {
def get(v: Variable): F[Option[Value]]
}
@newtype case class DbUrl(v: String)
@newtype case class DbUser(v: String)
@newtype case class DbPw(v: String)
final case class DbParams(url: DbUrl, user: DbUser, pw: DbPw)
trait DbConnector[F[_]] {
def read(url: DbUrl, user: DbUser, pw: DbPw): F[DbParams]
}
口译员如下:
object Environment {
def apply[F[_]](implicit ev: Environment[F]): ev.type = ev
def impl[F[_] : Sync]: Environment[F] = new Environment[F] {
override def get(v: Variable): F[Option[Value]] =
Sync[F].delay(sys.env.get(v.v).map(a => Value(a)))
}
}
final case class LiveDbConnector[F[_] : MonadError[*[_], Throwable]](env: Environment[F]) extends DbConnector[F] {
override def read(url: DbUrl, user: DbUser, pw: DbPw): F[DbParams] =
(for {
a <- OptionT(env.get(Variable(url.v)))
b <- OptionT(env.get(Variable(user.v)))
c <- OptionT(env.get(Variable(pw.v)))
} yield DbParams(DbUrl(a.v), DbUser(b.v), DbPw(c.v)))
.value
.flatMap {
case Some(v) => v.pure[F]
case None => DbSettingError.raiseError[F, DbParams]
}
}
object DbConnector {
def impl[F[_] : MonadError[*[_], Throwable]](env: Environment[F])
: DbConnector[F] =
new LiveDbConnector[F](env)
在函数式编程中,有 Monoid、Monads 等规律。
我的问题是:
- 我的代数是否需要法律或编写单元测试就足够了?
- 法律和单元测试有什么区别?
- 我应该如何写
DbConnector
代数定律