设为首页 加入收藏

TOP

Cats(3)- freeK-Free编程更轻松,Free programming with freeK(二)
2017-10-10 12:11:53 】 浏览:6692
Tags:Cats freeK-Free 编程 轻松 Free programming with freeK
interactLogin.nat)
6 // val r = authenticDSL.interpret(interactLogin) 7 import Dependencies._ 8 object UserPasswords extends PasswordControl { 9 override val mapPasswords: Map[String, String] = Map( 10 "Tiger" -> "123", 11 "John" -> "456" 12 ) 13 override def matchUserPassword(uid: String, pwd: String): Boolean = 14 mapPasswords.getOrElse(uid,pwd+"!") == pwd 15 } 16 17 interactLoginDSL.interpret(userInteractLogin).run(UserPasswords) 18 }

 

测试运行正常。现在我们要尝试三个独立DSL的组合了。先增加一个用户权限验证DSL:

 

1     sealed trait Auth[+A]
2     object Auth {
3       case class Authorize(uid: String) extends Auth[Boolean]
4     }

假如这个用户权限验证也是通过依赖注入的,我们先调整一下依赖界面:

 1 object Dependencies {  2  trait PasswordControl {  3  val mapPasswords: Map[String,String]  4  def matchUserPassword(uid: String, pswd: String): Boolean  5  }  6  trait AccessControl {  7  val mapAccesses: Map[String, Boolean]  8  def grandAccess(uid: String): Boolean  9  } 10  trait Authenticator extends PasswordControl with AccessControl 11 }

我们用Authenticator来代表包括PasswordControl,AccessControl的所有外部依赖。这样我们就需要把Reader的传入对象改变成Authenticator:

1  import Dependencies._ 2     type ReaderContext[A] = Reader[Authenticator,A]

首先我们把增加的Auth语法与前两个语法构成的Coproduct再集合,然后进行集合三种语法的DSL编程:

 1  import Auth._  2     type PRG3 = Auth :|: PRG   //Interact :|: Login :|: NilDSL
 3     val PRG3 = DSL.Make[PRG3]  4     val authorizeDSL: Free[PRG3.Cop, Unit] =
 5        for {  6          uid <- Ask("Enter your User ID:").freek[PRG3]  7          pwd <- Ask("Enter your Password:").freek[PRG3]  8          auth <- Authenticate(uid,pwd).freek[PRG3]  9          perm <-  if (auth) Authorize(uid).freek[PRG3] 10                   else Free.pure[PRG3.Cop,Boolean](false) 11           _ <- if (perm) Tell(s"Hello $uid, access granted!").freek[PRG3] 12                else Tell(s"Sorry $uid, access denied!").freek[PRG3] 13     } yield()

这个程序的功能具体实现方式如下:

1     val readerAuth = new (Auth ~> ReaderContext) { 2       def apply[A](aa: Auth[A]): ReaderContext[A] = aa match { 3         case Authorize(u) => Reader {ac => ac.grandAccess(u)} 4  } 5  } 6     val userAuth = readerAuth :&: userInteractLogin

下面是测试数据制作以及运算:

 1  import Dependencies._  2   object AuthControl extends Authenticator {  3     override val mapPasswords = Map(  4       "Tiger" -> "1234",  5       "John" -> "0000"
 6  )  7     override def matchUserPassword(uid: String, pswd: String) =
 8       mapPasswords.getOrElse(uid, pswd+"!") == pswd  9 
10     override val mapAccesses = Map ( 11       "Tiger" -> true, 12       "John" -> false
13  ) 14     override def grandAccess(uid: String) =
15       mapAccesses.getOrElse(uid, false) 16  } 17 
18 // interactLoginDSL.interpret(userInteractLogin).run(AuthControl)
19   authorizeDSL.interpret(userAuth).run(AuthControl)

测试运行结果:

 1 Enter your User ID:  2 Tiger  3 Enter your Password:  4 1234
 5 Hello Tiger, access granted!
 6 
 7 Process finished with exit code 0
 8 ...  9 Enter your User ID: 10 John 11 Enter your Password: 12 0000
13 Sorry John, access denied!
14 
15 Process finished with exit code 0

结果正是我们所预期的。在这次示范中我没费什么功夫就顺利的完成了一个三种语法DSL的编程示范。这说明freeK确实是个满意的Free编程工具。这次讨论的示范代码如下:

 1 import cats.free.Free  2 import cats.{Id, ~>}  3 import cats.data.Reader  4 import demo.app.FreeKModules.ADTs.Auth.Authorize  5 import freek._  6 object FreeKModules {  7   object ADTs {  8     sealed trait Interact[+A]  9     object Interact {  10       case class Ask(
首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Scala--高阶函数 下一篇scala学习手记36 - 容器基础

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目