新普金娱乐网址


数学好上核查子女有多主要?

《软件设计精要与方式》第①版设想数学

缘何将原始综合判断作为各科学的标准化?|康德《纯粹理性批判》精读(8)

  • 三月 03, 2019
  • 数学
  • 没有评论

 
 一贯深感FP相比虚,恐怕太多学术性的事物,不知情什么把这么些由数学理论在暗自支持的一套全新数据类型和数据结构在切实开发中加以运用。直到Free
Monad,才真的感到能用FP格局开始展览编制程序了。在后面大家已经花了相当的大篇幅来打探Free
Monad,本次笔者想跟大家斟酌一下用Free
Monad来编排3个确实能运作的全体应用程序。当然,那几个顺序必须具备FP特性,比如函数组合(function
composition),纯代码(pure code),延迟副成效(delayed side
effect)等等。大家本次模拟的三个采用场景是那般的:模拟2个总括器程序,用户先用密码登录;然后选拔操作,包罗加、减、乘、除;系统验证用户的操作权限;输入第3个数字,输入另一个数字,系统提交计算结果。程序在用户通过了密码登录后循环运维。大家先把程序须要里的一部分操作语句集罗列出来:

1.题解:在理性的全部争执科学中都涵盖有自然综合判断(synthetic a
priori)作为规范

① 、人机交互,Interact

此地要小心两点。首先,考察Lucas Thorpe的康德术语辞典(The Kant
Dictionary),康德将规则(rules)视为知性(understanding)的能力,而差别于条件(principles)为理性(reason)的能力。规则仅仅有一种概念效用,用以划分对象的范畴或开始展览范畴化(classify
objects)——通过规则的能力将对象分为属于或不属于的三个范围:

② 、用户登录,Login

They do this by serving as rules to potentially divide any set of
objects into two classes: those that fall under the concept and those
that do not.

③ 、权限决定,Permission

而规范(principles)则更具基础性。一方面,在辩论理性的见识中,原则是作为三段论首要前提的有史以来规则;从履行理性层面来看,原则是少校全部理性选择的守则,不论是相对律令(categorical
imperative)依然假言命令(hypothetical imperatives)皆属原则:

④ 、算术运算,Calculator

From the theoretical perspective a principle is a universal rule
that can function as a major premise in a syllogism. From the
practical perspective principles are practical laws that have the
function of governing our rational choice of maxims.
Both the
categorical imperative and hypothetical imperatives are principles in
this sense.**


那之中Login,Permission,Calculator都必须与Interact组合使用,因为它们都亟需交互式人工输入。这一次我们把研讨流程反过来:先把这几个顺序完整的算式(Algebraic
Data
Tree)、算法(Interpreter)以及借助注入、运算、结果等等先摆出来,然后再逐段分析表达:

其次点,“一切争论科学”,在康德的视野中指数学、自然科学和机械(农学)。由此标题标含义即为,这么些科学都是原始综合判断作为标准**

  1 package run.demo
  2 import scalaz._
  3 import Scalaz._
  4 import scala.language.higherKinds
  5 import scala.language.implicitConversions
  6 import run.demo.Modules.FreeCalculator.CalcInterp
  7 
  8 object Modules {
  9   object FreeInteract {
 10     trait Interact[+NextAct]
 11     object Interact {
 12       case class Ask[NextAct](prompt: String, onInput: String => NextAct) extends Interact[NextAct]
 13       case class Tell[NextAct](msg: String, n: NextAct) extends Interact[NextAct]
 14       implicit object interactFunctor extends Functor[Interact] {
 15          def map[A,B](ia: Interact[A])(f: A => B): Interact[B] = ia match {
 16            case Ask(p,onInput) => Ask(p, onInput andThen f)
 17            case Tell(m,n) => Tell(m, f(n))
 18          }
 19       } 
 20     }
 21     import Interact._
 22     object InteractConsole extends (Interact ~> Id) {
 23       def apply[A](ia: Interact[A]): Id[A] = ia match {
 24         case Ask(p,onInput) => println(p); onInput(readLine)
 25         case Tell(m, n) => println(m); n
 26       }
 27     }
 28     import FreeLogin._
 29     object InteractLogin extends (Interact ~> PasswordReader) {
 30       def apply[A](ia: Interact[A]): PasswordReader[A] = ia match {
 31         case Ask(p,onInput) => println(p); Reader(m => onInput(readLine))
 32         case Tell(m, n) => println(m); Reader(m => n)
 33       }
 34     }
 35     import FreePermission._
 36     object InteractPermission extends(Interact ~> PermissionReader) {
 37       def apply[A](ia: Interact[A]): PermissionReader[A] = ia match {
 38         case Ask(p,onInput) => println(p);Reader(m => onInput(readLine))
 39         case Tell(m,n) => println(m); Reader(m => n)
 40       }
 41     }
 42   }
 43   object FreeLogin {
 44     trait UserLogin[+A]
 45     object UserLogin {
 46       case class Login(uid: String, pswd: String) extends UserLogin[Boolean]
 47     } 
 48     import UserLogin._
 49     import Dependencies._
 50     type PasswordReader[A] = Reader[PasswordControl, A]
 51     object LoginInterp extends (UserLogin ~> PasswordReader) {
 52       def apply[A](la: UserLogin[A]): PasswordReader[A] = la match {
 53         case Login(uid,pswd) => Reader(m => m.matchPassword(uid, pswd))
 54       }
 55     }
 56   }
 57   object FreePermission {
 58     trait Permission[+A]
 59     object Permission {
 60       case class HasPermission(uid: String, opr: String) extends Permission[Boolean]
 61     }
 62     import Dependencies._
 63     import Permission._
 64     type PermissionReader[A] = Reader[PermissionControl,A]
 65     object PermissionInterp extends (Permission ~> PermissionReader) {
 66       def apply[A](pa: Permission[A]): PermissionReader[A] = pa match {
 67         case HasPermission(uid,opr) => Reader {m => m.matchPermission(uid, opr)}
 68       }
 69     }
 70   }
 71   object FreeCalculator {
 72     trait Calculator[+A]
 73     object Calculator {
 74       case class Calc(opr: String, lop: Int, rop: Int) extends Calculator[Int]
 75     }
 76     import Calculator._
 77     object CalcInterp extends (Calculator ~> Id) {
 78       def apply[A](ca: Calculator[A]): Id[A] = ca match {
 79         case Calc(opr,op1,op2) => opr.toUpperCase match {
 80           case "ADD" => op1 + op2
 81           case "SUB" => op1 - op2
 82           case "MUL" => op1 * op2
 83           case "DIV" => op1 / op2
 84         }
 85       }
 86     }
 87   }
 88   object FreeFunctions {
 89     import FreeInteract._
 90     import Interact._
 91     import FreeLogin._
 92     import UserLogin._
 93     import FreePermission._
 94     import Permission._
 95     import FreeCalculator._
 96     import Calculator._
 97     def lift[F[_],G[_],A](fa: F[A])(implicit I: Inject[F,G]): Free.FreeC[G,A] = 
 98        Free.liftFC(I.inj(fa)) 
 99     class Interacts[G[_]](implicit I: Inject[Interact,G]) {
100       def ask[A](prompt: String, onInput: String => A) = Free.liftFC(I.inj(Ask(prompt, onInput)))
101       def tell[A](msg: String) = Free.liftFC(I.inj(Tell(msg, ())))
102     }
103     object Interacts {
104       implicit def instance[F[_]](implicit I: Inject[Interact,F]) = new Interacts[F]
105     }
106     class Logins[G[_]](implicit I: Inject[UserLogin,G]) {
107       def login(uid: String, pswd: String) = lift(Login(uid,pswd))
108     }
109     object Logins {
110       implicit def instance[F[_]](implicit I: Inject[UserLogin,F]) = new Logins[F]
111     }
112     class Permissions[G[_]](implicit I: Inject[Permission,G]) {
113       def hasPermission(uid: String, opr: String) = lift(HasPermission(uid,opr))
114     }
115     object Permissions {
116       implicit def instance[F[_]](implicit I: Inject[Permission,F]) = new Permissions[F]
117     }
118     class Calculators[G[_]](implicit I: Inject[Calculator,G]) {
119       def calc(opr: String, op1: Int, op2: Int) = lift(Calc(opr,op1,op2))
120     }
121     object Calculators {
122       implicit def instance[F[_]](implicit I: Inject[Calculator,F]) = new Calculators[F]
123     }
124     def or[F[_],H[_],G[_]](fg: F ~> G, hg: H ~> G): ({type l[x] = Coproduct[F,H,x]})#l ~> G =
125       new (({type l[x] = Coproduct[F,H,x]})#l ~> G) {
126        def apply[A](ca: Coproduct[F,H,A]): G[A] = ca.run match {
127          case -\/(x) => fg(x)
128          case \/-(y) => hg(y)
129        }
130     }
131   }
132   object FreeProgs {
133     import FreeFunctions._
134     import FreeInteract._
135     import FreeLogin._
136     import FreePermission._
137     import FreeCalculator._
138     def freeCMonad[S[_]] = Free.freeMonad[({type l[x] = Coyoneda[S,x]})#l]
139     def loginScript[F[_]](implicit I: Interacts[F], L: Logins[F]) = {
140       import I._
141       import L._
142       for {
143         uid <- ask("ya id:",identity)
144         pwd <- ask("password:",identity)
145         login <- login(uid,pwd)
146         _ <- if (login) tell("ya in, ya lucky bastard!")
147                 else tell("geta fk outa here!")
148         usr <- if (login) freeCMonad[F].point(uid) 
149                else freeCMonad[F].point("???")
150       } yield usr
151     }
152     def accessScript[F[_]](uid: String)(implicit I: Interacts[F], P: Permissions[F]) = {
153       import I._
154       import P._
155       for {
156         inp <- ask("votiu vangto do?",identity)
157         cando <- hasPermission(uid,inp)
158         _ <- if (cando) tell("ok, go on ...")
159                 else tell("na na na, cant do that!")   
160         opr <- if (cando) freeCMonad[F].point(inp) 
161                else freeCMonad[F].point("XXX")
162       } yield opr
163        
164     }
165 
166     def calcScript[F[_]](opr: String)(implicit I: Interacts[F], C: Calculators[F]) = {
167       import I._;import C._;
168       for {
169         op1 <- ask("fus num:", _.toInt)
170         op2 <- ask("nx num:", _.toInt)
171         result <- calc(opr,op1,op2)
172       } yield result
173     }
174 
175     type LoginScript[A] = Coproduct[Interact, UserLogin, A]
176     type CalcScript[A] = Coproduct[Interact, Calculator, A]
177     type AccessScript[A] = Coproduct[Interact, Permission, A]
178     val accessPrg = accessScript[AccessScript] _
179     val loginPrg = loginScript[LoginScript]
180     val calcPrg = calcScript[CalcScript] _
181   }
182 }
183 object Dependencies {
184   trait PasswordControl {
185     val pswdMap: Map[String,String]
186     def matchPassword(uid: String, pswd: String): Boolean
187   }
188   trait PermissionControl {
189     val permMap: Map[String,List[String]]
190     def matchPermission(uid: String, operation: String): Boolean
191   }
192 }
193 object FreeProgram extends App {
194   import Modules._
195   import FreeInteract._
196   import FreeLogin._
197   import FreePermission._
198   import FreeFunctions._
199   import FreeProgs._
200   import Dependencies._
201   object Passwords extends PasswordControl {
202      val pswdMap = Map (
203        "Tiger" -> "1234",
204        "John" -> "0332"
205      )
206      def matchPassword(uid: String, pswd: String) = pswdMap.getOrElse(uid, pswd+"!") === pswd
207   }
208   object AccessRights extends PermissionControl {
209      val permMap = Map (
210        "Tiger" -> List("Add","Sub"),
211        "John" -> List("Mul","Div")
212      )
213      def matchPermission(uid: String, opr: String) = permMap.getOrElse(uid, List()).exists { _ === opr}
214   }
215   
216   val uid = Free.runFC(loginPrg)(or(InteractLogin, LoginInterp)).run(Passwords)
217   val opr = Free.runFC(accessScript[AccessScript](uid))(or(InteractPermission, PermissionInterp)).run(AccessRights)
218   val sum = Free.runFC(calcScript[CalcScript](opr))(or(InteractConsole, CalcInterp))
219   println(uid)
220   println(opr)
221   println(sum)
222 }
223 //测试运算结果
224 ya id:
225 Tiger
226 password:
227 1234
228 ya in, ya lucky bastard!
229 votiu vangto do?
230 Add
231 ok, go on ...
232 fus num:
233 3
234 nx num:
235 7
236 Tiger
237 Add
238 10

看起来好像费了老大劲就做那么点事。但要是我们依照Free
Monadic编制程序的正统来做,一切仅仅有条无需多想,那也正是那么点事。实际上在编写更大型更复杂的先后时应当会觉着思路更显著,代码量会更不难,因为成功的函数组合可以幸免过多双重代码。基本的Free
Monadic 编制程序步骤大体如下:

2.导言第陆节第③段:

1、ADT design  

数学的判断全部都以综合的。那条定律如同到现在从不被人类理性的分析家们注意到,甚至恰好与他们的方方面面臆想相反,就算它兼具不可能辩护的鲜明性并有格外重要的结局。那是因为,人们由于看到科学家的推测都以依照争持律进行的(那是其他一种科学的鲜明的本性所供给的),于是就使和谐相信,数学原理也是出于争辨律而被认可的;他们在这边是弄错了;因为,2个归纳命题即使可以依照顶牛律来通晓,但不得不是那样来了然,即有此外三个归结命题作为前提,它能从那此外几个归纳命题中推出去,而不用是就其自个儿来了解的。

2、ADT Free
lifting

这一某些主要化解数学的判断全体都以综合的这一命题。首先康德辨析数学的判定究竟是综合的仍旧分析的。

3、ADT
composition、AST composition

亚里士多德在《形而上学》中觉得“任何事物在同如今间不容许既存在又不设有”,矛盾律藉此而来,即对于任意命题p,p和非p不可能在同一时半刻间、同一方面同时为真,依据此,如果任意二个命题包蕴争执,则为假,遵照亚里士Dodd的传道,那是“全数标准中最领悟的规格。”但是,康德此处颠覆了龃龉律的本体意义,相反,一些定律确实是基于、符合争持律的,至少在领略层面,假设命题有争论表明全部论证推论进度存在难题,只怕说不齐全。

4、Dependency
design

而是,我们切不可因为表面上符合那个规则,就将以此规则正是最根本的组织原则。例如,光的折射原理,光在差异介质中会产生折射,光确实会产生折射的,然而并不是说光的实质上就有1个【可折射性】,只是光在某种环境中符合那样的法则。由此,顶牛律只是1个外显的规律,任何形成的命题必然符合争执律,可是毫无出自于争执律。康德意识到了那或多或少。

5、Interpreter
design

康德认为数学判断全部都以综合的,相反,从前任何文学家们(Kant:人类理性的分析家们)并非如此,而是觉得数学判断分歧于自然科学等文化,是分析的。原因就在于,他们误解了上述有关抵触律的难点。1个综合命题能够由此争论律来掌握,不过其本人并非是基于抵触律来组织的,同样,1个综合命题看上去就像是是分析的,不过它自身并非是透过分析的艺术来布局的,依照康德的说法,大家可以清楚为三个归纳命题是由另3个归纳命题推出来的,例如大家早期学习乘法的时候,5×6=30,是由加法5+5+5+5+5+5推出去的。所以,那么些人类理性的分析家们直接以来都搞错了。

6、Running and
dependency injection

**3.导言第四节第贰段:**

一 、ADTs:
遵照效益须求规划编程语句。个中值得注意的是Interact:


 1    trait Interact[+NextAct]
 2     object Interact {
 3       case class Ask[NextAct](prompt: String, onInput: String => NextAct) extends Interact[NextAct]
 4       case class Tell[NextAct](msg: String, n: NextAct) extends Interact[NextAct]
 5       implicit object interactFunctor extends Functor[Interact] {
 6          def map[A,B](ia: Interact[A])(f: A => B): Interact[B] = ia match {
 7            case Ask(p,onInput) => Ask(p, onInput andThen f)
 8            case Tell(m,n) => Tell(m, f(n))
 9          }
10       } 
11     }
12  

先是必须注意的是:真正的数学命题总是后天判断而不是经验性的判断,因为它们有着不可能从经验中取得的必然性。但倘诺人们不愿接受这点,那么好,作者将把团结的命题局限于纯粹数学,这一概念的题中应有之义是:它不带有经验性的学问,而只包涵纯粹的纯天然知识。

Interact能够协理map,必须是个Functor。那是因为里面2个动静Ask供给对输入String进行转换后跻身下3个气象。

紧接着康德继续起首辨析,真正的数学命题总是后天判断,而不是经验性判断,因为数学命题都须要通过认证,即就是经过总结法得出的下结论,也要实行论证,那样才拥有普遍性、必然性。可是,人们常常不会容许,因为不少数学命题已经和生活阅历贴合得太紧凑了,就像是已经这一个费用大量一日千里举行求证和理解不复存在了。所以,康德退而求其次,将范围减弱到纯粹数学,至少在这一限制内,它不包罗其余经验性的学问。

二 、升格lifting:大家要求把那些ADT都升级成Free。因为有点ADT不是Functor,所以用liftFC把它们统一升级为FreeC:

**4.导言第⑥节第2段:**

 1   object FreeFunctions {
 2     import FreeInteract._
 3     import Interact._
 4     import FreeLogin._
 5     import UserLogin._
 6     import FreePermission._
 7     import Permission._
 8     import FreeCalculator._
 9     import Calculator._
10     def lift[F[_],G[_],A](fa: F[A])(implicit I: Inject[F,G]): Free.FreeC[G,A] = 
11        Free.liftFC(I.inj(fa)) 
12     class Interacts[G[_]](implicit I: Inject[Interact,G]) {
13       def ask[A](prompt: String, onInput: String => A) = Free.liftFC(I.inj(Ask(prompt, onInput)))
14       def tell[A](msg: String) = Free.liftFC(I.inj(Tell(msg, ())))
15     }
16     object Interacts {
17       implicit def instance[F[_]](implicit I: Inject[Interact,F]) = new Interacts[F]
18     }
19     class Logins[G[_]](implicit I: Inject[UserLogin,G]) {
20       def login(uid: String, pswd: String) = lift(Login(uid,pswd))
21     }
22     object Logins {
23       implicit def instance[F[_]](implicit I: Inject[UserLogin,F]) = new Logins[F]
24     }
25     class Permissions[G[_]](implicit I: Inject[Permission,G]) {
26       def hasPermission(uid: String, opr: String) = lift(HasPermission(uid,opr))
27     }
28     object Permissions {
29       implicit def instance[F[_]](implicit I: Inject[Permission,F]) = new Permissions[F]
30     }
31     class Calculators[G[_]](implicit I: Inject[Calculator,G]) {
32       def calc(opr: String, op1: Int, op2: Int) = lift(Calc(opr,op1,op2))
33     }
34     object Calculators {
35       implicit def instance[F[_]](implicit I: Inject[Calculator,F]) = new Calculators[F]
36     }
37     def or[F[_],H[_],G[_]](fg: F ~> G, hg: H ~> G): ({type l[x] = Coproduct[F,H,x]})#l ~> G =
38       new (({type l[x] = Coproduct[F,H,x]})#l ~> G) {
39        def apply[A](ca: Coproduct[F,H,A]): G[A] = ca.run match {
40          case -\/(x) => fg(x)
41          case \/-(y) => hg(y)
42        }
43     }
44   }

虽说人们最初差不离会想:7+5=12那一个命题是三个单独分析命题,它是从7加5之和的定义中依照矛盾律推出去的。不过,假若人们更近乎地观测一下,那么就会意识,7加5之和的概念并未蕴含别的更进一步的事物,而只含有那七个数结为二个数的趣味,那种重组根本没有使人想到那几个把二者总合起来的绝世的数是哪位数。12这几个定义并非是出于我单是思考非凡7与5的组合就被想到了,并且,不论小编把自身有关那样2个大概的总和的概念分析多么久,我毕竟不会在里面找到12。大家亟须高于这么些概念之外,借助于与这七个概念之一相应的直观,例如我们的七个手指,也许(如谢格奈在其《算术》中所说的)三个点,那样2个2个地把直观中予以的五的这几个单位加到七的定义上去。因为本身首先取的是7以此数,并且,由于自家为了5那么些定义而求助于笔者的指头的直观,于是作者就将本人原先合起来构成5那几个数的那贰个单位凭借自个儿手指的影像1个一个地加到7这几个数上去,那样就观察12这一个数发生了。要把5加在7之上,这点笔者即便在有个别等于7+5的和的定义中早已想到了,但并没有想到那个和非凡12那几个数。所以算术命题永远都是综合的;对此我们更为取更大的数量,就越是看得更了然,因为那样一来就通晓地彰显出,不论大家什么把大家的定义颠来倒去,大家若不借助于直观而只依靠对大家的概念作分析,是永远不容许发现这一个总和的。

在lift函数中应用了scalaz提供的Inject类型实例,用来把F[A]这种类型转换来G[A]。能够知道为把一组语句F[A]流入更大的话语集G[A](G[A]可以是F[A],那时转换结果为一摸一样的语句集)。也许因为Interact和任何ADT分裂,是个Functor,所以在调用lift函数进行进步时compiler会发生错误类型推导结果,直接调用liftFC能够消除难题,那一个留到未来继续商讨。以后这几个提高了的口舌集都具备了隐式实例implicit
instance,随时可以在隐式解析域内提供操作语句协理。

此地康德为了论证数学判断全是归纳的,分析了7+5=12以此算术命题。整个式子7+5,“依照争持律”,无法是其余数,只可以是12,那就是所谓的依照龃龉律所出产的,然则这么存在三个标题,当我们谈到【不是其余数】的时候,鲜明将本人落入了二个宏伟的集聚中,这几个集合中的数字是无穷多的,大家无能为力透过争辨律一一比对,因而,数学算式正如前边所说,
十分的小概是依照争论律构造的。

三 、ASTs:未来有了那么些基础语句集,遵照职能供给,我们得以用某一种语句组合成一个程序AST,也许结合用两种以上语句组合程序,甚至把发生的AST组合成更大的次第。大家得以用scalaz的Coproduct来落到实处那几个语句集的一块儿:

**5.导言第4节第6段:**
**

1     type LoginScript[A] = Coproduct[Interact, UserLogin, A]
2     type CalcScript[A] = Coproduct[Interact, Calculator, A]
3     type AccessScript[A] = Coproduct[Interact, Permission, A]
4     val accessPrg = accessScript[AccessScript] _
5     val loginPrg = loginScript[LoginScript]
6     val calcPrg = calcScript[CalcScript] _

同样,纯粹几何学的别样1个规律也不是分析性的。两点时期直线最短,那是3个归纳命题。因为本身的直的概念并非蕴涵大小的定义,而只包括某种性质。故此“最短”这么些概念完全是加上去的,而得不到通过分析从直线这几个概念中引出来。由此在此处不可不依靠直观,唯有依靠直观这一归咎才是唯恐的。在那边,平时使大家觉得那种科学的论断的谓词已经给予我们的概念之中、因此该论断就像正是分析性的那种信念,只可是是措辞含混所致。因为大家应该在1个给予的定义上再想出某些谓词来,而那种须求性已经附着于那多少个概念身上了。但难题不在于大家相应想出哪些来加在那么些给予的定义上,而在于大家在那几个定义中其实想到了什么,固然只是模糊地想到了怎么着,而那就标明,那谓词即便必然地与这概念相联系,但决不作为在概念自个儿中所想到的,而是依靠有些必须加在那概念上的直观。

这里有个环节尤其要求小心:理论上大家得以用Coproduct联合二种以上语句集:

继之举办数学的另3个方面(几何学)的论据。“两点间的直线”并不能够一向生产“最短”,而是当大家早已直观到了,在全部命题中,两点间的直线连起来最短,所以才将双方对等起来的。由此,它不是八个解析命题,而是综合命题。实际上,当我们着想“两点间的直线”这一命题的时候,已经发现到这些命题蕴涵着某些必然性,正如上一段所言,7加5之后必定会得出贰个数,可是大家想到的不会是“最短”那几个概念。换言之,仅仅经过分析,大家只可以知道这样一种必然性,不过最后还是要靠综合判定,靠直观来连接二者。

1     type F0[A] = Coproduct[Interact,UserLogin,A]
2     type F1[A] = Coproduct[Permission,F0,A]
3     type F2[A] = Coproduct[Calculator,F1,A]
4     val loginPrg2 = loginScript[F1]

6.**导言第陆节第四段:**

但loginPrg2发生以下编写翻译错误:

几何学作为前提的少数几条规律就算真正是分析的,并且是制造在抵触律之上的;但它们正如这一个同一性命题一样,也只是用来方法上的连年,而不是当做规范(they
serve only to form the chain of method and serve not as
principles),
譬如说a=a,即全部与作者相等,或(a+b)>a,亦即一切大于其有个别。并且即到底这一个原理本人,就算只有遵照概念的话就是卓有成效的,但它们在数学中因故行得通,也只是因为它们能在直观中浮现出来。

not enough arguments for method loginScript: (implicit I: run.demo.Modules.FreeFunctions.Interacts[run.demo.Modules.FreeProgs.F1], implicit L: run.demo.Modules.FreeFunctions.Logins[run.demo.Modules.FreeProgs.F1], implicit P: run.demo.Modules.FreeFunctions.Permissions[run.demo.Modules.FreeProgs.F1])scalaz.Free[[x]scalaz.Coyoneda[run.demo.Modules.FreeProgs.F1,x],String]. Unspecified value parameters L, P.

本段中,康德认可的确有个别数学命题是分析的,并且是起家在争持律之上的,不过所谓的辨析只是方式上的,而非原则上的,那里类同与本节先是段,康德对争论律的本体意义举办反拨的那部分,换言之,大家由此将少数几条几何学中的原理看成是分析的,是因为她们真的符合于争辩律,可是不要真正的以顶牛律为规范建立起来的。言下之意正是,数学命题在尺度上接二连三综合的,而不是分析的,就算只是依照概念的话,能够说是分析的,大家也的确看到它是分析的,可是究其本质而言,唯有经过直观才能判断,它大概含有着可分析的层面,但本质上是归纳的。例如大家真正能够从花的颜色去看清花那几个项目,可是究其本质,颜色并非是花的原形,大家不能够说花正是一种颜色、一些颜料,由颜色组合。

本人开头分析或许是因为scalaz对Free设下的秘诀:F[A]必须是个Functor。在lift函数的Inject[F,G]中,目的类型G[_]最终会被升级为Free
Monad,若是大家使用Free.liftF函数的话G[_]无法不是Functor。恐怕选取Free.liftFC后造成compiler无法符合规律开始展览项目推测吧。近年来新生产的Cats组件库中Free的概念不必要Functor,有可能消除这些难题。因为Free只怕变为今后的一种关键编制程序形式,所以必须想办法化解多语句集一起使用的难题。可是大家把这么些松手今后再说。

7.**导言第伍节第陆段:**
**

今昔我们得以用升格了的言语编制程序了,也正是函数组合:

自然科学(物历史学)包罗后天综合判定作为本人中的原则。自家只想举出多个定理作例子,一个定律是:在物质世界的一体变化中,物质的量保持不变;另二个定律是:在活动的上上下下传递中,功用和反效果自然永远相等。鲜明,在这七个命题上,不仅仅留存着必然性,于是其来自是后天性的,而且它们也是总结命题。因为在物质概念中自身并不曾想到持久不变,而只想到物质经过对空间的充满而在上空中参加。所以为了后天地对物质概念再想出某种本身在它当中没有想到的事物,笔者实在超出了物质概念。为此这条定律不是三个剖析命题,而是综合的,但却是后天被想到的,并且自然科学纯粹部分的其余部分定律也都是这么。

 1  object FreeProgs {
 2     import FreeFunctions._
 3     import FreeInteract._
 4     import FreeLogin._
 5     import FreePermission._
 6     import FreeCalculator._
 7     def freeCMonad[S[_]] = Free.freeMonad[({type l[x] = Coyoneda[S,x]})#l]
 8     def loginScript[F[_]](implicit I: Interacts[F], L: Logins[F]) = {
 9       import I._
10       import L._
11       for {
12         uid <- ask("ya id:",identity)
13         pwd <- ask("password:",identity)
14         login <- login(uid,pwd)
15         _ <- if (login) tell("ya in, ya lucky bastard!")
16                 else tell("geta fk outa here!")
17         usr <- if (login) freeCMonad[F].point(uid) 
18                else freeCMonad[F].point("???")
19       } yield uid
20     }
21     def accessScript[F[_]](uid: String)(implicit I: Interacts[F], P: Permissions[F]) = {
22       import I._
23       import P._
24       for {
25         inp <- ask("votiu vangto do?",identity)
26         cando <- hasPermission(uid,inp)
27         _ <- if (cando) tell("ok, go on ...")
28                 else tell("na na na, cant do that!")   
29         opr <- if (cando) freeCMonad[F].point(inp) 
30                else freeCMonad[F].point("XXX")
31       } yield inp
32        
33     }
34 
35     def calcScript[F[_]](opr: String)(implicit I: Interacts[F], C: Calculators[F]) = {
36       import I._;import C._;
37       for {
38         op1 <- ask("fus num:", _.toInt)
39         op2 <- ask("nx num:", _.toInt)
40         result <- calc(opr,op1,op2)
41       } yield result
42     }
43 
44     type LoginScript[A] = Coproduct[Interact, UserLogin, A]
45     type CalcScript[A] = Coproduct[Interact, Calculator, A]
46     type AccessScript[A] = Coproduct[Interact, Permission, A]
47     val accessPrg = accessScript[AccessScript] _
48     val loginPrg = loginScript[LoginScript]
49     val calcPrg = calcScript[CalcScript] _   
50   }

接下去初阶论证自然科学。康德举了三个例子,第3个【在物质世界的全数变化中,物质的量保持不变】,当大家分析【物质】这一概念的时候,并从未推出【不变】那么些结果,而只是想到分布在空间中的各类存在、实体,而【物质的量保持不变】是三个总结的直观后的下结论(同时期的化学革命,Lava锡,化学中的物质守恒定律)。第一个,功效力与反功用力那五个概念并不可能向来生产双方是相当的,而唯有靠综合判断,并且这一归结判断不是后天经验赢得的,而是自然想到的、直观到的。这一后天综合判定无法从命题中剖析出来,同时也不供给依赖于经验,而是由理性所科普同意和自然地明显的,是直观到的

能够看到,以上每3个顺序都相比简单,简单明白。那也是FP的表征:从简单基本的程序起头,经过持续整合形成全体应用。

Kant is claiming that these judgements do not just provide us with
knowledge of our concepts, but provide us with insight into the object
our concepts refer to.

四 、Dependency
injection:稍有规模的程序都有恐怕要求借助此外程序来提供一些意义。所以在那么些事例里示范了一些借助注入:

不过,康德的那四个例证鲜明如她的数学例子一样不够标准,又大概是康德理论本人的难题所在。例如第一个大体定律,其实在现代物军事学中,在物质世界的全数变化中,物质的量并非一直维系不变,它还是可以够改为能量(can
be converted into energy)。数学,

 1 object Dependencies {
 2   trait PasswordControl {
 3     val pswdMap: Map[String,String]
 4     def matchPassword(uid: String, pswd: String): Boolean
 5   }
 6   trait PermissionControl {
 7     val permMap: Map[String,List[String]]
 8     def matchPermission(uid: String, operation: String): Boolean
 9   }
10 }

7.**导言第肆节第八段:**
**

伍 、Interpreter:在运算程序时(program
interpretation),可以根据须要调用重视中的效用:

在形而上学中,尽管我们把它仅仅作为一门到现在还只是在品味、但却由于人类理性的秉性而不行缺点和失误的正确,也相应包涵后天综合的知识,并且它所关怀的一直不是可是对我们关于事物的原始造成的定义加以解释、由此作出分析的印证,相反,我们要壮大大家的原状知识,为此大家必须运用那样有些规律,它们在被提交的定义上加码了里面没有包括的某种东西,并因而自然综合判定完全远远地超越了该概念,以至于大家的经验自个儿也不可能跟随这么远,例如在“世界自然有2个早期的起来”等命题中那么,因而形而上学至少就其指标而言是由纯粹先天综合命题所结合的。

1     import Dependencies._
2     type PasswordReader[A] = Reader[PasswordControl, A]
3     object LoginInterp extends (UserLogin ~> PasswordReader) {
4       def apply[A](la: UserLogin[A]): PasswordReader[A] = la match {
5         case Login(uid,pswd) => Reader(m => m.matchPassword(uid, pswd))
6       }
7     }

最终到了经济学,固然历史学还未根本的确立,不够成熟,不过康德从军事学的指标来看,认为其一定是有纯粹后天综合命题所结合的,因为理学的目标决不仅仅是关切大家已知先天知识的不停分解和注脚,而是要推而广之我们的原生态知识,所以医学那门发展中的科学中一定要包括着原生态综合判定。

留神,当三种语句联合利用时,它们会被撤换(natural
transformation)成同一个目的语句集,所以当Interact和UserLogin联合利用时都会进展PasswordReader类型的转换。由于Interact是一项最宗旨的功能,与别的ADT联合使用发挥效果,所以要为每一个一块ADT提供特种的Interpreter:

 1     object InteractConsole extends (Interact ~> Id) {
 2       def apply[A](ia: Interact[A]): Id[A] = ia match {
 3         case Ask(p,onInput) => println(p); onInput(readLine)
 4         case Tell(m, n) => println(m); n
 5       }
 6     }
 7     import FreeLogin._
 8     object InteractLogin extends (Interact ~> PasswordReader) {
 9       def apply[A](ia: Interact[A]): PasswordReader[A] = ia match {
10         case Ask(p,onInput) => println(p); Reader(m => onInput(readLine))
11         case Tell(m, n) => println(m); Reader(m => n)
12       }
13     }
14     import FreePermission._
15     object InteractPermission extends(Interact ~> PermissionReader) {
16       def apply[A](ia: Interact[A]): PermissionReader[A] = ia match {
17         case Ask(p,onInput) => println(p);Reader(m => onInput(readLine))
18         case Tell(m,n) => println(m); Reader(m => n)
19       }
20     }

一如既往,联合语句集编成的次第必须有照应的运算方法。大家特地为Coproduct类型的演算提供了or函数:

**往期:**

1     def or[F[_],H[_],G[_]](fg: F ~> G, hg: H ~> G): ({type l[x] = Coproduct[F,H,x]})#l ~> G =
2       new (({type l[x] = Coproduct[F,H,x]})#l ~> G) {
3        def apply[A](ca: Coproduct[F,H,A]): G[A] = ca.run match {
4          case -\/(x) => fg(x)
5          case \/-(y) => hg(y)
6        }

康德《纯粹理性批判》精读(7)

Coproduce是把八个语句集放在左右两边。大家只须要历遍Coproduct结构每种运算结构中的语句。

康德《纯粹理性批判》精读(6)

六 、running
program:由于大家把全数语句都升级成了FreeC类型,所以必须调用runFC函数来运营。作为FP程序延迟副成效示范,大家在先后真的运算时才把重视注入进来:

康德《纯粹理性批判》精读(5)

 1 object FreeProgram extends App {
 2   import Modules._
 3   import FreeInteract._
 4   import FreeLogin._
 5   import FreePermission._
 6   import FreeFunctions._
 7   import FreeProgs._
 8   import Dependencies._
 9   object Passwords extends PasswordControl {
10      val pswdMap = Map (
11        "Tiger" -> "1234",
12        "John" -> "0332"
13      )
14      def matchPassword(uid: String, pswd: String) = pswdMap.getOrElse(uid, pswd+"!") === pswd
15   }
16   object AccessRights extends PermissionControl {
17      val permMap = Map (
18        "Tiger" -> List("Add","Sub"),
19        "John" -> List("Mul","Div")
20      )
21      def matchPermission(uid: String, opr: String) = permMap.getOrElse(uid, List()).exists { _ === opr}
22   }
23   
24   val uid = Free.runFC(loginPrg)(or(InteractLogin, LoginInterp)).run(Passwords)
25   val opr = Free.runFC(accessScript[AccessScript](uid))(or(InteractPermission, PermissionInterp)).run(AccessRights)
26   val sum = Free.runFC(calcScript[CalcScript](opr))(or(InteractConsole, CalcInterp))
27   println(uid)
28   println(opr)
29   println(sum)
30 }

康德《纯粹理性批判》精读(4)

但是这么些事例还不算是3个完好无损的次序。大家印象中的完整应用应该还要加上交互循环、错误提醒等等。大家能否用FP方式来完善这几个例子吗?先说循环呢(looping):FP循环不就是递归嘛(recursion),实在可怜就试试Trampoline。关于程序的流程序控制制:我们能够在节点之间传递3个场合,代表下一步的操作:

康德《纯粹理性批判》精读(3)

1     trait NextStep  //状态: 下一步操作
2     case object Login extends NextStep  //登录,用户信息验证
3     case class End(msg: String) extends NextStep  //正常结束退出
4     case class Opr(uid: String) extends NextStep  //计算操作选项及权限验证
5     case class Calc(uid: String, opr: String) extends NextStep //计算操作

康德《纯粹理性批判》精读(2)

将来我们得以编写制定1个函数来运算每八个步骤:

康德《纯粹理性批判》精读(1)

 1     def runStep(step: NextStep): Exception \/ NextStep = {
 2       try {
 3        step match {
 4         case Login => {
 5          Free.runFC(loginPrg)(or(InteractLogin, LoginInterp)).run(Passwords) match {
 6            case "???" => End("Termination! Login failed").right
 7            case uid: String => Opr(uid).right
 8            case _ => End("Abnormal Termination! Unknown error.").right
 9          }
10         }
11         case Opr(uid) =>
12           Free.runFC(accessScript[AccessScript](uid))(or(InteractPermission, PermissionInterp)).
13           run(AccessRights) match {
14             case "XXX" => Opr(uid).right
15             case opr: String => if (opr.toUpperCase.startsWith("Q")) End("End at user request。").right
16                                 else Calc(uid,opr).right
17             case _ => End("Abnormal Termination! Unknown error.").right
18           }
19         case Calc(uid,opr) => 
20           println(Free.runFC(calcScript[CalcScript](opr))(or(InteractConsole, CalcInterp)))
21           Opr(uid).right
22        }
23       }
24       catch {
25          case e: Exception => e.left[NextStep]  
26       }
27     }

在这么些函数里大家扩张了uid=”XXX”,opr.toUpperCase.startWith(“Q”)以及opr=”???”那多少个情形。需求调整一下AccessScript和LoginScript:

 1   object FreeProgs {
 2     import FreeFunctions._
 3     import FreeInteract._
 4     import FreeLogin._
 5     import FreePermission._
 6     import FreeCalculator._
 7     def freeCMonad[S[_]] = Free.freeMonad[({type l[x] = Coyoneda[S,x]})#l]
 8     def loginScript[F[_]](implicit I: Interacts[F], L: Logins[F]) = {
 9       import I._
10       import L._
11       for {
12         uid <- ask("ya id:",identity)
13         pwd <- ask("password:",identity)
14         login <- login(uid,pwd)
15         _ <- if (login) tell("ya in, ya lucky bastard!")
16                 else tell("geta fk outa here!")
17         usr <- if (login) freeCMonad[F].point(uid) 
18                else freeCMonad[F].point("???")
19       } yield usr
20     }
21     def accessScript[F[_]](uid: String)(implicit I: Interacts[F], P: Permissions[F]) = {
22       import I._
23       import P._
24       for {
25         inp <- ask("votiu vangto do?",identity)
26         cando <- if (inp.toUpperCase.startsWith("Q")) freeCMonad[F].point(true) else hasPermission(uid,inp)
27         _ <- if (cando) freeCMonad[F].point("")
28                 else tell("na na na, cant do that!")   
29         opr <- if (cando) freeCMonad[F].point(inp) 
30                else freeCMonad[F].point("XXX")
31       } yield opr
32        
33     }
34 
35     def calcScript[F[_]](opr: String)(implicit I: Interacts[F], C: Calculators[F]) = {
36       import I._;import C._;
37       for {
38         op1 <- ask("fus num:", _.toInt)
39         op2 <- ask("nx num:", _.toInt)
40         result <- calc(opr,op1,op2)
41       } yield result
42     }

下一场我们能够进行巡回互动了:

1     import scala.annotation.tailrec
2     @tailrec
3     def whileRun(state: Exception \/ NextStep): Unit = state match {
4       case \/-(End(msg)) => println(msg)
5       case \/-(nextStep: NextStep) => whileRun(runStep(nextStep))
6       case -\/(e) => println(e)
7       case _ => println("Unknown exception!")
8     }

那是一个尾递归算法(tail
recursion)。测试运维 :

1 object FreeProgram extends App {
2   import Modules._
3   import FreeRunner._
4   whileRun(Login.right)
5 }

下边是测试结果:

ya id:
Tiger
password:
1234
ya in, man!
votiu vangto do?
Add
fus num:
12
nx num:
5
got ya self a 17.
votiu vangto do?
23
na na na, can't do that!
votiu vangto do?
Sub
fus num:
23
nx num:
5
got ya self a 18.
votiu vangto do?
quit
End at user request。

ya id:
John
password:
1234
geta fk outa here!, you bastard
Termination! Login failed

ya id:
John
password:
0332
ya in, man!
votiu vangto do?
Add
na na na, can't do that!
votiu vangto do?
Mul
fus num:
3
nx num:
7
got ya self a 21.
votiu vangto do?
Div
fus num:
10
nx num:
3
got ya self a 3.
votiu vangto do?
Div
fus num:
12
nx num:
0
Abnormal termination!
java.lang.ArithmeticException: / by zero

咱俩也得以用Trampoline来循环运算那么些示范:

1     import scalaz.Free.Trampoline
2     import scalaz.Trampoline._
3     def runTrampoline(state: Exception \/ NextStep): Trampoline[Unit] = state match {
4       case \/-(End(msg)) => done(println(msg))
5       case \/-(nextStep: NextStep) => suspend(runTrampoline(runStep(nextStep)))
6       case -\/(e) => done({println("Abnormal termination!"); println(e)})
7       case _ => done(println("Unknown exception!"))
8     }

测试运算:

1 object FreeProgram extends App {
2   import Modules._
3   import FreeRunner._
4 //  whileRun(Login.right)
5   runTrampoline(Login.right).run            
6 }

测试运算结果:

 

ya id:
Tiger
password:
1234
ya in, man!
votiu vangto do?
Sub
fus num:
12
nx num:
15
got ya self a -3.
votiu vangto do?
Mul
na na na, can't do that!
votiu vangto do?
Add
fus num:
10
nx num:
5
got ya self a 15.
votiu vangto do?
quit
End at user request。

 

好了,上面是其一示范的一体化源代码:

 

  1 package run.demo
  2 import scalaz._
  3 import Scalaz._
  4 import scala.language.higherKinds
  5 import scala.language.implicitConversions
  6 import run.demo.Modules.FreeCalculator.CalcInterp
  7 
  8 object Modules {
  9   object FreeInteract {
 10     trait Interact[+NextAct]
 11     object Interact {
 12       case class Ask[NextAct](prompt: String, onInput: String => NextAct) extends Interact[NextAct]
 13       case class Tell[NextAct](msg: String, n: NextAct) extends Interact[NextAct]
 14       implicit object interactFunctor extends Functor[Interact] {
 15          def map[A,B](ia: Interact[A])(f: A => B): Interact[B] = ia match {
 16            case Ask(p,onInput) => Ask(p, onInput andThen f)
 17            case Tell(m,n) => Tell(m, f(n))
 18          }
 19       } 
 20     }
 21     import Interact._
 22     object InteractConsole extends (Interact ~> Id) {
 23       def apply[A](ia: Interact[A]): Id[A] = ia match {
 24         case Ask(p,onInput) => println(p); onInput(readLine)
 25         case Tell(m, n) => println(m); n
 26       }
 27     }
 28     import FreeLogin._
 29     object InteractLogin extends (Interact ~> PasswordReader) {
 30       def apply[A](ia: Interact[A]): PasswordReader[A] = ia match {
 31         case Ask(p,onInput) => println(p); Reader(m => onInput(readLine))
 32         case Tell(m, n) => println(m); Reader(m => n)
 33       }
 34     }
 35     import FreePermission._
 36     object InteractPermission extends(Interact ~> PermissionReader) {
 37       def apply[A](ia: Interact[A]): PermissionReader[A] = ia match {
 38         case Ask(p,onInput) => println(p);Reader(m => onInput(readLine))
 39         case Tell(m,n) => println(m); Reader(m => n)
 40       }
 41     }
 42   }
 43   object FreeLogin {
 44     trait UserLogin[+A]
 45     object UserLogin {
 46       case class Login(uid: String, pswd: String) extends UserLogin[Boolean]
 47     } 
 48     import UserLogin._
 49     import Dependencies._
 50     type PasswordReader[A] = Reader[PasswordControl, A]
 51     object LoginInterp extends (UserLogin ~> PasswordReader) {
 52       def apply[A](la: UserLogin[A]): PasswordReader[A] = la match {
 53         case Login(uid,pswd) => Reader(m => m.matchPassword(uid, pswd))
 54       }
 55     }
 56   }
 57   object FreePermission {
 58     trait Permission[+A]
 59     object Permission {
 60       case class HasPermission(uid: String, opr: String) extends Permission[Boolean]
 61     }
 62     import Dependencies._
 63     import Permission._
 64     type PermissionReader[A] = Reader[PermissionControl,A]
 65     object PermissionInterp extends (Permission ~> PermissionReader) {
 66       def apply[A](pa: Permission[A]): PermissionReader[A] = pa match {
 67         case HasPermission(uid,opr) => Reader {m => m.matchPermission(uid, opr)}
 68       }
 69     }
 70   }
 71   object FreeCalculator {
 72     trait Calculator[+A]
 73     object Calculator {
 74       case class Calc(opr: String, lop: Int, rop: Int) extends Calculator[Int]
 75     }
 76     import Calculator._
 77     object CalcInterp extends (Calculator ~> Id) {
 78       def apply[A](ca: Calculator[A]): Id[A] = ca match {
 79         case Calc(opr,op1,op2) => opr.toUpperCase match {
 80           case "ADD" => op1 + op2
 81           case "SUB" => op1 - op2
 82           case "MUL" => op1 * op2
 83           case "DIV" => op1 / op2
 84         }
 85       }
 86     }
 87   }
 88   object FreeFunctions {
 89     import FreeInteract._
 90     import Interact._
 91     import FreeLogin._
 92     import UserLogin._
 93     import FreePermission._
 94     import Permission._
 95     import FreeCalculator._
 96     import Calculator._
 97     def lift[F[_],G[_],A](fa: F[A])(implicit I: Inject[F,G]): Free.FreeC[G,A] = 
 98        Free.liftFC(I.inj(fa)) 
 99     class Interacts[G[_]](implicit I: Inject[Interact,G]) {
100       def ask[A](prompt: String, onInput: String => A) = Free.liftFC(I.inj(Ask(prompt, onInput)))
101       def tell[A](msg: String) = Free.liftFC(I.inj(Tell(msg, ())))
102     }
103     object Interacts {
104       implicit def instance[F[_]](implicit I: Inject[Interact,F]) = new Interacts[F]
105     }
106     class Logins[G[_]](implicit I: Inject[UserLogin,G]) {
107       def login(uid: String, pswd: String) = lift(Login(uid,pswd))
108     }
109     object Logins {
110       implicit def instance[F[_]](implicit I: Inject[UserLogin,F]) = new Logins[F]
111     }
112     class Permissions[G[_]](implicit I: Inject[Permission,G]) {
113       def hasPermission(uid: String, opr: String) = lift(HasPermission(uid,opr))
114     }
115     object Permissions {
116       implicit def instance[F[_]](implicit I: Inject[Permission,F]) = new Permissions[F]
117     }
118     class Calculators[G[_]](implicit I: Inject[Calculator,G]) {
119       def calc(opr: String, op1: Int, op2: Int) = lift(Calc(opr,op1,op2))
120     }
121     object Calculators {
122       implicit def instance[F[_]](implicit I: Inject[Calculator,F]) = new Calculators[F]
123     }
124     def or[F[_],H[_],G[_]](fg: F ~> G, hg: H ~> G): ({type l[x] = Coproduct[F,H,x]})#l ~> G =
125       new (({type l[x] = Coproduct[F,H,x]})#l ~> G) {
126        def apply[A](ca: Coproduct[F,H,A]): G[A] = ca.run match {
127          case -\/(x) => fg(x)
128          case \/-(y) => hg(y)
129        }
130     }
131   }
132   object FreeProgs {
133     import FreeFunctions._
134     import FreeInteract._
135     import FreeLogin._
136     import FreePermission._
137     import FreeCalculator._
138     def freeCMonad[S[_]] = Free.freeMonad[({type l[x] = Coyoneda[S,x]})#l]
139     def loginScript[F[_]](implicit I: Interacts[F], L: Logins[F]) = {
140       import I._
141       import L._
142       for {
143         uid <- ask("ya id:",identity)
144         pwd <- ask("password:",identity)
145         login <- login(uid,pwd)
146         _ <- if (login) tell("ya in, man!")
147                 else tell("geta fk outa here!, you bastard")
148         usr <- if (login) freeCMonad[F].point(uid) 
149                else freeCMonad[F].point("???")
150       } yield usr
151     }
152     def accessScript[F[_]](uid: String)(implicit I: Interacts[F], P: Permissions[F]) = {
153       import I._
154       import P._
155       for {
156         inp <- ask("votiu vangto do?",identity)
157         cando <- if (inp.toUpperCase.startsWith("Q")) freeCMonad[F].point(true) else hasPermission(uid,inp)
158         _ <- if (cando) freeCMonad[F].point("")
159                 else tell("na na na, can't do that!")   
160         opr <- if (cando) freeCMonad[F].point(inp) 
161                else freeCMonad[F].point("XXX")
162       } yield opr
163        
164     }
165 
166     def calcScript[F[_]](opr: String)(implicit I: Interacts[F], C: Calculators[F]) = {
167       import I._;import C._;
168       for {
169         op1 <- ask("fus num:", _.toInt)
170         op2 <- ask("nx num:", _.toInt)
171         result <- calc(opr,op1,op2)
172       } yield result
173     }
174 
175     type LoginScript[A] = Coproduct[Interact, UserLogin, A]
176     type CalcScript[A] = Coproduct[Interact, Calculator, A]
177     type AccessScript[A] = Coproduct[Interact, Permission, A]
178     val accessPrg = accessScript[AccessScript] _
179     val loginPrg = loginScript[LoginScript]
180     val calcPrg = calcScript[CalcScript] _   
181   }
182   object FreeRunner {
183     import FreeInteract._
184     import FreeLogin._
185     import FreePermission._
186     import FreeFunctions._
187     import FreeProgs._
188     import Dependencies._
189     trait NextStep  //状态: 下一步操作
190     case object Login extends NextStep  //登录,用户信息验证
191     case class End(msg: String) extends NextStep  //正常结束退出
192     case class Opr(uid: String) extends NextStep  //计算操作选项及权限验证
193     case class Calc(uid: String, opr: String) extends NextStep //计算操作
194     object Passwords extends PasswordControl {
195       val pswdMap = Map (
196        "Tiger" -> "1234",
197        "John" -> "0332"
198       )
199       def matchPassword(uid: String, pswd: String) = pswdMap.getOrElse(uid, pswd+"!") === pswd
200     }   
201     object AccessRights extends PermissionControl {
202        val permMap = Map (
203          "Tiger" -> List("Add","Sub"),
204          "John" -> List("Mul","Div")
205        )
206        def matchPermission(uid: String, opr: String) = permMap.getOrElse(uid, List()).exists { _ === opr}
207     }    
208     def runStep(step: NextStep): Exception \/ NextStep = {
209       try {
210        step match {
211         case Login => {
212          Free.runFC(loginPrg)(or(InteractLogin, LoginInterp)).run(Passwords) match {
213            case "???" => End("Termination! Login failed").right
214            case uid: String => Opr(uid).right
215            case _ => End("Abnormal Termination! Unknown error.").right
216          }
217         }
218         case Opr(uid) =>
219           Free.runFC(accessScript[AccessScript](uid))(or(InteractPermission, PermissionInterp)).
220           run(AccessRights) match {
221             case "XXX" => Opr(uid).right
222             case opr: String => if (opr.toUpperCase.startsWith("Q")) End("End at user request。").right
223                                 else Calc(uid,opr).right
224             case _ => End("Abnormal Termination! Unknown error.").right
225           }
226         case Calc(uid,opr) => 
227           println(s"got ya self a ${Free.runFC(calcScript[CalcScript](opr))(or(InteractConsole, CalcInterp))}.")
228           Opr(uid).right
229        }
230       }
231       catch {
232          case e: Exception => e.left[NextStep]  
233       }
234     }
235     import scala.annotation.tailrec
236     @tailrec
237     def whileRun(state: Exception \/ NextStep): Unit = state match {
238       case \/-(End(msg)) => println(msg)
239       case \/-(nextStep: NextStep) => whileRun(runStep(nextStep))
240       case -\/(e) => println("Abnormal termination!"); println(e)
241       case _ => println("Unknown exception!")
242     }
243     import scalaz.Free.Trampoline
244     import scalaz.Trampoline._
245     def runTrampoline(state: Exception \/ NextStep): Trampoline[Unit] = state match {
246       case \/-(End(msg)) => done(println(msg))
247       case \/-(nextStep: NextStep) => suspend(runTrampoline(runStep(nextStep)))
248       case -\/(e) => done({println("Abnormal termination!"); println(e)})
249       case _ => done(println("Unknown exception!"))
250     }
251   }
252 }
253 object Dependencies {
254   trait PasswordControl {
255     val pswdMap: Map[String,String]
256     def matchPassword(uid: String, pswd: String): Boolean
257   }
258   trait PermissionControl {
259     val permMap: Map[String,List[String]]
260     def matchPermission(uid: String, operation: String): Boolean
261   }
262 }
263 object FreeProgram extends App {
264   import Modules._
265   import FreeRunner._
266 //  whileRun(Login.right)
267   runTrampoline(Login.right).run            
268 }

 

 

 

 

相关文章

No Comments, Be The First!
近期评论
    分类目录
    功能
    网站地图xml地图