6

わかりましたので、ラムダ計算の基本を実装しようとしています。ここに行きます。

私の番号:

def zero[Z](s: Z => Z)(z: Z): Z = z
def one[Z](s: Z => Z)(z: Z): Z = s(z)
def two[Z](s: Z => Z)(z: Z): Z = s(s(z))

それらの部分的に (実際には、非) 適用されたバージョンは、次のようになります。

def z[Z]: (Z => Z) => (Z => Z) = zero _

続行する前に、いくつかの型を定義します。

type FZ[Z] = Z => Z
type FFZ[Z] = FZ[Z] => FZ[Z]

関数succは次のようになります (アプリケーションの順序は正確にそのようにする必要があります!ここで定義を取りました):

def succ[Z](w: FFZ[Z])(y: FZ[Z])(x: Z): Z = y((w(y))(x))

そして、適用されていないバージョンは次のように恐ろしいものになります。

def s[Z]: FFFZ[Z] = successor _

ご容赦ください。不足しているタイプは次のとおりです。

type FFFZ[Z] = FFZ[Z] => FFZ[Z]
type FFFFZ[Z] = FFFZ[Z] => FFFZ[Z]

しかし、私はそのadd機能に行き詰まっています。タイプと定義に準拠している場合(ここでも同様)、次のようになります

def add[Z](a: FFFFZ[Z])(b: FFZ[Z]): FFZ[Z] =
  (a(s))(b)

aしかし、私は一般的なタイプの数になりたいですFFZ[Z]

では、足し算はどのように定義すればよいのでしょうか?

4

2 に答える 2

4

数値、ブール値、およびペアをコーディングしました: https://github.com/pedrofurla/church/blob/master/src/main/scala/Church.scala教会のスタイルに従っています。

私が気づいたことの 1 つは、カリー化された関数構文を使用する方が、複数の引数リストを使用するよりもはるかに簡単だということです。興味深いスニペットのいくつか

type NUM[A] = (A => A) => A => A
def succ  [A]: NUM[A]  =>  NUM[A] = m => n => x => n(m(n)(x))
def zero  [A]: NUM[A] = f => x => x
def one   [A]: NUM[A] = f => x => f(x)
def two   [A]: NUM[A] = f => x => f(f(x))
def three [A]: NUM[A] = f => x => f(f(f(x)))
def plus  [A]: (NUM[A]) => (NUM[A]) => NUM[A] = m => n => f => x => m(f)(n(f)(x))

今すぐそれらを印刷します(Antov Trunovのソリューションに非常に似ています):

def nvalues[A] = List(zero[A], one[A], two[A], three[A])

val inc: Int => Int  = _ + 1 
def num: (NUM[Int]) => Int = n => n(inc)(0)
def numStr: (NUM[String]) => String = n => n("f (" + _ + ") ")("z")

いくつかの出力:

scala> println(nvalues map num)
List(0, 1, 2, 3)

scala> println(nvalues map numStr) // Like this better :)
List(z, f (z) , f (f (z) ) , f (f (f (z) ) ) )
于 2016-04-22T21:15:50.717 に答える