2016-06-10 70 views
7

在Haskell自由的實現是:在scalaz免費實施

data Free f a = 
Pure a 
| Free (f (Free f a)) 

,而在Scalaz實現如下:

sealed abstract class Free[S[_], A] 

private case class Return[S[_], A](a: A) extends Free[S, A] 
private case class Suspend[S[_], A](a: S[A]) extends Free[S, A] 
private case class Gosub[S[_], B, C](a: Free[S, C], f: C => Free[S, B]) extends Free[S, B] 

爲什麼不相似的scalaz實施哈斯克爾,如:

sealed trait Free[F[_],A] 
case class Return[F[_],A](a: A) extends Free[F,A] 
case class GoSub[F[_],A](s: F[Free[F,A]]) extends Free[F,A] 

這兩種實現是同構的嗎?

+0

如果使用第二個Scala實現給出一個'F [A]',你會如何創建一個'Free [F,A]? –

+0

@PeterNeyens,當'F'是'Functor'時,這是非常有可能的。這種表示的問題在於它會導致堆棧安全問題。 –

+1

@TomasMikula。好的,我看到'GoSub [F,A](F.map(fa)(Return [F,A](_))'',謝謝! –

回答

7

的是Haskell代碼Scala的翻譯是

sealed abstract class Free[S[_], A] 

case class Return[S[_], A](a: A) extends Free[S, A] 
case class Suspend[S[_], A](a: S[Free[S, A]]) extends Free[S, A] 

Haskell的實現並不需要Gosub情況下,由於懶惰的評估。這種表示方式也可以在Scala中使用,但由於(嚴格評估和缺少尾部消除消除),它會導致堆棧溢出問題。爲了使IT架構安全的,我們代表flatMap懶洋洋地,爲Gosub(我認爲FlatMap將是一個更好的名字):

case class Gosub[S[_], B, C](a: Free[S, C], f: C => Free[S, B]) extends Free[S, B] 

作爲獎勵,引進Gosub使我們能夠簡化Suspend

case class Suspend[S[_], A](a: S[A]) extends Free[S, A] 

因爲我們不需要通過映射S[_]的內容來做flatMap s —我們將flatMap明確地表示爲Gosub s。

因此,與Haskell表示形式不同,此結果表示允許我們做任何想做的事情,而不需要Functor[S]。所以當我們的S不是Functor時,我們甚至不需要混淆「Coyoneda技巧」。