簡體   English   中英

為無標簽代數編寫法律或單元測試

[英]Write laws or unit test for tagless algebras

我已經寫了兩個無標簽代數,我想為其中一個寫定律。

代數如下:

@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 等規律。

我的問題是:

  1. 我的代數是否需要法律或編寫單元測試就足夠了?
  2. 法律和單元測試有什么區別?
  3. 我應該如何為DbConnector代數編寫定律

您將數學定律和合理性與程序的正確性混淆了。

首先,Monad、Monoid、Fold 等不是定律。 它們是來自范疇論的數學“結構”。 這些“結構”具有它們需要遵守、健全和正確的某些特性。 例如,其中一組屬性被稱為一元定律

數學中的任何一元結構都需要遵守以下 3 條規則:

  1. 左身份
  2. 正確的身份
  3. 關聯性

Monad、flatMap 和 pure(或數學中的 join 和 return)上的操作必須正確地遵守 function 的這些定律。 pure(a).flatMap(f) == f(a)M.flatMap(pure) == M等。

在函數式編程中,Monads 是一種從這些數學結構和規律中衍生出來的設計模式。 他們描述了一些“可組合的計算”。 在貓中 Monad 被定義為typeclass 這種結構符合上述規則。

我應該如何為 DbConnector 代數編寫定律

如果你想證明定律,你可能需要使用定理證明器,實際上沒有辦法在 Scala 中明確編寫或測試定律,但你總是可以編寫單元測試來確保你的 Monad 遵守這些定律,即testFlatMapLeftIdentity(...)等。

我的代數是否需要法律或編寫單元測試就足夠了?

簡而言之,我想不出代數有明確的規律的情況,除非你的代數描述了一些數學運算集。 例如,在您的代碼中,上下文綁定MonadError[*[_], Throwable]]需要 scope 中的Monad[F] ,假設您使用的是常見的IO, Task, Future等,則需要遵守這些法律,貓已經做到了,所以你不必擔心這些法律。 如果您決定實現自己的效果類型或編寫新的 Monad 實現,您將需要確保遵守這些規則,但您的代碼中沒有任何內容需要您擔心它們。 為這個代數編寫好的單元測試就足夠了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM