2014-05-17 20 views
6

Bu yüzden comonad.com, uygulayıcılarla çalışma konusunda ilginç bir dizi makaleye sahiptir ve ben (örneğin, eğlenmek ve öğrenmek için) ölçeklendirmek için elimden geleni yapmaya çalışıyorum. Yani, haskell FixF tanımlar -Scalada Haskell FixF tanımlanması

yazıldığı
newtype FixF f a = FixF (f (FixF f) a) 

," FixF tür ((* -> *) -> * -> *) -> * -> *) olan kendine ait fixpoint alır. 'Ikinci dereceden funktoru' (başka funktoru bir funktor gönderen bir funktoru, yani bir endofunctor standart "birinci derece Functor" geri almak için, hask) funk kategorisinde. "

kinds classify types 
*     type A 
* -> *    type F[_] 
* -> * -> *   type F[_,_] 
((* -> *) -> *)  type F[F'[_]] 
((* -> *) ->* -> *) type F[F'[_], A] 

Şimdi bu

case class Fix[F[_]](out: F[Fix[F]]) 
// ((* -> *) -> *) 

ve bu

case class BFixF[F[_,_], A](out: F[A, BFixF[F,A]]) 

Yani ilk Fix (yanlış türde) ikinci mı değil mi gördün? o

// edit as of this morning it is really not this 
    class FixF[F[_[_], _], A] :: ((* -> *) -> * -> *) -> *) 

- ı

BFixF :: ((* -> * -> *) -> * -> *) ? 

öyle türlü doğru olduğunu sanmıyorum?

case class FixF'[F[_], A](run: F[Fix[F, A]]) 

Birisi uygulamalı tanımlayabilir doğru tanımını ve functor şimdi

case class FixF[F[_], A] (out: F[Fix[F, A]]) 

trait FixFFunctor[F[_]: Functor] extends Functor[({type l[x] = FixF[F, x]})#l] { 

    def map[A, B](f: A => B): FixF[F, A] => FixF[F, B] = ??? 

} 

ikramiye sorusu görmek isteriz eğer öyleyse? Ben FixF hakkında daha fazla bilgi edinmek zaman sonra cevap genişletmeye çalışacağım

import scala.language.higherKinds 

class FixF[F[_,_],A](val ffix: F[FixF[F,_],A]) extends AnyVal; 

:

+0

Bu etiketlenmiş [python]? Neden görmüyorum? –

+0

Bu soru python'u etiketlemek için hiçbir neden yoktur. Açıkçası python'a hiçbir şey olmadığı gibi. – DEAD

cevap

8

Bu oldukça güzel bir soru: Ayrıca bu mesajları okudum ve bir Scala uygulamasının ne kadar korkunç göründüğünü merak ettim, ama aslında hiç denemedim. Bu yüzden biraz ayrıntıya cevap vereceğim, ancak aşağıdakilerin aşırı derecede kapalı olduğunu unutmayın (Cumartesi sabahı, her şeyden önce) ve mutlaka Scala'da bunu yapmanın en temiz yolunu temsil etmiyor.

import scala.language.higherKinds 
import scalaz._, Scalaz._ 

case class Const[M, A](mo: M) 

sealed trait Sum[F[_], G[_], A] 

object Sum { 
    def inL[F[_], G[_], A](l: F[A]): Sum[F, G, A] = InL(l) 
    def inR[F[_], G[_], A](r: G[A]): Sum[F, G, A] = InR(r) 
} 

case class InL[F[_], G[_], A](l: F[A]) extends Sum[F, G, A] 
case class InR[F[_], G[_], A](r: G[A]) extends Sum[F, G, A] 

Ve daha blog post itself gelen bir çift:

O first post in the series gelen türlerinden bazıları tanımlayarak başlamak en iyisi

case class Embed[F[_], A](out: A) 

case class ProductF[F[_[_], _], G[_[_], _], B[_], A](f: F[B, A], g: G[B, A]) 

Yukarıdaki aracılığıyla çalıştıysanız, FixF'un neye benzemesi gerektiği konusunda biraz bilgi sahibi olmalısınız:

case class FixF[F[f[_], _], A](out: F[({ type L[x] = FixF[F, x] })#L, A]) 

Bu da, biraz fazla sıkı olduğu ortaya çıktı, bu yüzden yerine aşağıdaki kullanacağız:

class FixF[F[f[_], _], A](v: => F[({ type L[x] = FixF[F, x] })#L, A]) { 
    lazy val out = v 
    override def toString = s"FixF($out)" 
} 

Şimdi bir "polinom functors ikinci dereceden fixpoint" olarak listelerini uygulamak istediğinizi varsayalım, blog yazısında olduğu gibi. Biz bazı yararlı adlar tanımlayarak başlatabilirsiniz:

type UnitConst[x] = Const[Unit, x] 
type UnitConstOr[F[_], x] = Sum[UnitConst, F, x] 
type EmbedXUnitConstOr[F[_], x] = ProductF[Embed, UnitConstOr, F, x] 

type MyList[x] = FixF[EmbedXUnitConstOr, x] 

Ve şimdi görevinden örneklerinden Scala sürümünü tanımlayabilirsiniz:

val foo: MyList[String] = new FixF[EmbedXUnitConstOr, String](
    ProductF[Embed, UnitConstOr, MyList, String](
    Embed("foo"), 
    Sum.inL[UnitConst, MyList, String](Const()) 
) 
) 

val baz: MyList[String] = new FixF[EmbedXUnitConstOr, String](
    ProductF[Embed, UnitConstOr, MyList, String](
    Embed("baz"), 
    Sum.inL[UnitConst, MyList, String](Const()) 
) 
) 

val bar: MyList[String] = new FixF[EmbedXUnitConstOr, String](
    ProductF[Embed, UnitConstOr, MyList, String](
    Embed("bar"), 
    Sum.inR[UnitConst, MyList, String](baz) 
) 
) 

Biz Haskell uygulaması verilen beklediğiniz gibi görünüyor : Tür sınıfı örneklerine ihtiyacımız var. Bunların çoğu oldukça basittir:

implicit def applicativeConst[M: Monoid]: Applicative[ 
    ({ type L[x] = Const[M, x] })#L 
] = new Applicative[({ type L[x] = Const[M, x] })#L] { 
    def point[A](a: => A): Const[M, A] = Const(mzero[M]) 
    def ap[A, B](fa: => Const[M, A])(f: => Const[M, A => B]): Const[M, B] = 
    Const(f.mo |+| fa.mo) 
} 

implicit def applicativeEmbed[F[_]]: Applicative[ 
    ({ type L[x] = Embed[F, x] })#L 
] = new Applicative[({ type L[x] = Embed[F, x] })#L] { 
    def point[A](a: => A): Embed[F, A] = Embed(a) 
    def ap[A, B](fa: => Embed[F, A])(f: => Embed[F, A => B]): Embed[F, B] = 
    Embed(f.out(fa.out)) 
} 

implicit def applicativeProductF[F[_[_], _], G[_[_], _], B[_]](implicit 
    fba: Applicative[({ type L[x] = F[B, x] })#L], 
    gba: Applicative[({ type L[x] = G[B, x] })#L] 
): Applicative[({ type L[x] = ProductF[F, G, B, x] })#L] = 
    new Applicative[({ type L[x] = ProductF[F, G, B, x] })#L] { 
    def point[A](a: => A): ProductF[F, G, B, A] = 
     ProductF(fba.point(a), gba.point(a)) 
    def ap[A, C](fa: => ProductF[F, G, B, A])(
     f: => ProductF[F, G, B, A => C] 
    ): ProductF[F, G, B, C] = ProductF(fba.ap(fa.f)(f.f), gba.ap(fa.g)(f.g)) 
    } 

FixF kendisi için uygulamalı örneği dahildir:

implicit def applicativeFixF[F[_[_], _]](implicit 
    ffa: Applicative[({ type L[x] = F[({ type M[y] = FixF[F, y] })#M, x] })#L] 
): Applicative[({ type L[x] = FixF[F, x] })#L] = 
    new Applicative[({ type L[x] = FixF[F, x] })#L] { 
    def point[A](a: => A): FixF[F, A] = new FixF(ffa.pure(a)) 
    def ap[A, B](fa: => FixF[F, A])(f: => FixF[F, A => B]): FixF[F, B] = 
     new FixF(ffa.ap(fa.out)(f.out)) 
    } 

Ayrıca, terminal dönüşümü tanımlarsınız:

implicit def terminal[F[_], M: Monoid]: F ~> ({ type L[x] = Const[M, x] })#L = 
    new (F ~> ({ type L[x] = Const[M, x] })#L) { 
    def apply[A](fa: F[A]): Const[M, A] = Const(mzero[M]) 
    } 

Ama şimdi bizler başı dertte olmak. Biz gerçekten burada bazı ekstra tembelliğini gerek, bu yüzden biraz hile edeceğiz:

def applicativeSum[F[_], G[_]](
    fa: Applicative[F], 
    ga: => Applicative[G], 
    nt: G ~> F 
): Applicative[({ type L[x] = Sum[F, G, x] })#L] = 
    new Applicative[({ type L[x] = Sum[F, G, x] })#L] { 
    def point[A](a: => A): Sum[F, G, A] = InR(ga.point(a)) 
    def ap[A, B](x: => Sum[F, G, A])(f: => Sum[F, G, A => B]): Sum[F, G, B] = 
     (x, f) match { 
     case (InL(v), InL(f)) => InL(fa.ap(v)(f)) 
     case (InR(v), InR(f)) => InR(ga.ap(v)(f)) 
     case (InR(v), InL(f)) => InL(fa.ap(nt(v))(f)) 
     case (InL(v), InR(f)) => InL(fa.ap(v)(nt(f))) 
     } 
    } 

implicit def myListApplicative: Applicative[MyList] = 
    applicativeFixF[EmbedXUnitConstOr](
    applicativeProductF[Embed, UnitConstOr, MyList](
     applicativeEmbed[MyList], 
     applicativeSum[UnitConst, MyList](
     applicativeConst[Unit], 
     myListApplicative, 
     terminal[MyList, Unit] 
    ) 
    ) 
) 

Belki bu kesmek olmadan applicatives ait Scalaz 7'nin kodlama ile çalışmak için almak için bir yol var, ama don varsa' Cumartesi öğleden sonralarımı anlamaya çalışmak istiyorum.

Yani berbat, ama en azından şimdi yaptığımız işi kontrol edebilirsiniz: biz tam olarak ne istediğini

scala> println((foo |@| bar)(_ ++ _)) 
FixF(ProductF(Embed(foobar),InL(Const(())))) 

.

+1

Müthiş. çok takdir edildi. – DEAD

0

Sadece Haskell veri türü bakarak, şu sınıfını çalışacaktı.