Last active
October 14, 2015 11:59
-
-
Save xuwei-k/469a2213c7773274272f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
scalaVersion := "2.11.6" | |
libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.1.1" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scalaz._ | |
import Free.FreeC | |
class DDD[Entity, ID] { | |
// repositoryへの操作を代数的データ型で定義し、それをFreeとCoyonedaの力によりモナドにして使う | |
sealed abstract class RepositoryDSL[A] | |
// 見つからないかもしれないので結果はOption型 | |
final case class ResolveBy(id: ID) extends RepositoryDSL[Option[Entity]] | |
// storeするentityそのまま返す。必要ないなら、戻り値型Unitでもいいかも? | |
// それとも、IDは引数渡すのではなく、Repository側で発行すべき? | |
final case class Store(id: ID, entity: Entity) extends RepositoryDSL[Entity] | |
def resolveBy(id: ID): FreeC[RepositoryDSL, Option[Entity]] = | |
Free.liftFC(ResolveBy(id)) | |
def store(id: ID, entity: Entity): FreeC[RepositoryDSL, Entity] = | |
Free.liftFC(Store(id, entity)) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scalaz._ | |
import scalaz.Id.Id | |
object Sample { | |
type UserId = Int | |
final case class User(id: UserId, name: String) | |
// 型パラメータを当てはめるためだけにnewしてるけど、ここはもっと色々やり方ありそう | |
val ddd = new DDD[User, UserId] | |
// ダミーのデータベース | |
val database = collection.mutable.Map.empty[UserId, User] | |
// これは単純にscalazのId型(identityモナド)で、エラーが発生しない、エラー処理を行わないことにしてあるが、 | |
// RepositoryDSL ~> Either 型へのインタプリタを作ることにより、エラーを処理することも可能 | |
val interpreter = new (ddd.RepositoryDSL ~> Id) { | |
def apply[A](fa: ddd.RepositoryDSL[A]) = fa match { | |
case ddd.ResolveBy(id) => | |
database.get(id) | |
case ddd.Store(id, entity) => | |
database.put(id, entity) | |
entity | |
} | |
} | |
val user1 = User(1, "aaa") | |
val user2 = User(2, "bbb") | |
def main(args: Array[String]): Unit = { | |
// for式でプログラムを組み立てる | |
// 組み立てるだけで、実際にインタプリタを渡さないと、まだ実行はされない | |
val program = for { | |
_ <- ddd.store(user1.id, user1) | |
_ <- ddd.store(user2.id, user2) | |
user <- ddd.resolveBy(user1.id) | |
} yield user | |
val result = Free.runFC(program)(interpreter) | |
println(result) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment