# Scalaz（32）－ Free ：lift - Monad生产线

```/** A free operational monad for some functor `S`. Binding is done using the heap instead of the stack,
* allowing tail-call elimination. */
sealed abstract class Free[S[_], A] {
...
/** Return from the computation with the given value. */
private[scalaz] case class Return[S[_], A](a: A) extends Free[S, A]

/** Suspend the computation with the given suspension. */
private[scalaz] case class Suspend[S[_], A](a: S[Free[S, A]]) extends Free[S, A]
...```

1、Free[S[_],A]可以代表一个运算

```  /** Suspends a value within a functor in a single step. Monadic unit for a higher-order monad. */
def liftF[S[_], A](value: => S[A])(implicit S: Functor[S]): Free[S, A] =
Suspend(S.map(value)(Return[S, A]))```

liftF可以把一个S[A]升格成Free[S,A]。我们用个例子来证明：

``` 1 package Exercises
2 import scalaz._
3 import Scalaz._
4 import scala.language.higherKinds
5 import scala.language.implicitConversions
6 object freelift {
7 trait Config[+A] {
8   def get: A
9 }
10 object Config {
11   def apply[A](a: A): Config[A] = new Config[A] { def get = a}
12   implicit val configFunctor = new Functor[Config] {
13      def map[A,B](ca: Config[A])(f: A => B) = Config[B](f(ca.get))
14   }
15 }
16
17 val freeConfig = Free.liftF(Config("hi config"))  //> freeConfig  : scalaz.Free[Exercises.freelift.Config,String] = Suspend(Exercises.freelift\$Config\$\$anon\$2@d70c109)```

```1 trait Interact[+A]  //Console交互
2 //println(prompt: String) then readLine 返回String
3 case class Ask(prompt: String) extends Interact[String]
4 //println(msg: String) 不反回任何值
5 case class Tell(msg: String) extends Interact[Unit]```

```1 Free.liftFC(Tell("hello"))                        //> res0: scalaz.Free.FreeC[Exercises.freelift.Interact,Unit] = Suspend(scalaz.Coyoneda\$\$anon\$22@71423665)
2 Free.liftFC(Ask("how are you"))                   //> res1: scalaz.Free.FreeC[Exercises.freelift.Interact,String] = Suspend(scalaz.Coyoneda\$\$anon\$22@20398b7c)```

```  /** A version of `liftF` that infers the nested type constructor. */
def liftFU[MA](value: => MA)(implicit MA: Unapply[Functor, MA]): Free[MA.M, MA.A] =
liftF(MA(value))(MA.TC)

/** A free monad over a free functor of `S`. */
def liftFC[S[_], A](s: S[A]): FreeC[S, A] =
liftFU(Coyoneda lift s)```

Coyoneda lift s 返回结果Coyoneda[S,A], liftFU用Unapply可以把Coyoneda[S,A]转化成S[A]并提供给liftF。看看Unapply这段：

```  /**Unpack a value of type `M0[A0, B0]` into types `[a]M0[a, B0]` and `A`, given an instance of `TC` */
implicit def unapplyMAB1[TC[_[_]], M0[_, _], A0, B0](implicit TC0: TC[({type λ[α] = M0[α, B0]})#λ]): Unapply[TC, M0[A0, B0]] {
type M[X] = M0[X, B0]
type A = A0
} = new Unapply[TC, M0[A0, B0]] {
type M[X] = M0[X, B0]
type A = A0
def TC = TC0
def leibniz = refl
}

/**Unpack a value of type `M0[A0, B0]` into types `[b]M0[A0, b]` and `B`, given an instance of `TC` */
implicit def unapplyMAB2[TC[_[_]], M0[_, _], A0, B0](implicit TC0: TC[({type λ[α] = M0[A0, α]})#λ]): Unapply[TC, M0[A0, B0]] {
type M[X] = M0[A0, X]
type A = B0
} = new Unapply[TC, M0[A0, B0]] {
type M[X] = M0[A0, X]
type A = B0
def TC = TC0
def leibniz = refl
}```

``` 1 package Exercises
2 import scalaz._
3 import Scalaz._
4 import scala.language.higherKinds
5 object interact {
6 trait Interact[+A]
7 case class Ask[Next](prompt: String, n: String => Next) extends Interact[Next]
8 case class Tell[Next](msg: String, n: Next) extends Interact[Next]
9
10 object interFunctor extends Functor[Interact] {
11   def map[A,B](ia: Interact[A])(f: A => B): Interact[B] = ia match {
12       case Tell(m,n) => Tell(m, f(n))
14   }
15 }```

0 条评论

## 相关文章

### BookNote: Refactoring - Improving the Design of Existing Code

2696

1、dirver package com.kangaroo.hadoop.drive; import java.util.Map; import java.u...

6395

### 来自国外Kotin 布道师的 完整版【Kotlin 简明教程】1Kotlin 开发者社区

A programming language is usually designed with a specific purpose in mind. This...

1372

### Koltin Any 类型Koltin Any 类型

The root of the Kotlin class hierarchy. Every Kotlin class has Any as a supercla...

672

812

### 聊聊springboot2的LoggersEndpoint

spring-boot-actuator-autoconfigure-2.0.1.RELEASE-sources.jar!/org/springframewor...

1182

21010

### 聊聊rocketmq的FileAppender

org/apache/rocketmq/logging/inner/LoggingBuilder.java

551

581

### 聊聊storm client的nimbus.seeds参数

storm-core-1.1.0-sources.jar!/org/apache/storm/Config.java

1062