3 回答

TA貢獻1995條經(jīng)驗 獲得超2個贊
當你使用更高級的類型時,類型lambda是非常重要的。
考慮一個簡單的例子,為Either [A,B]的正確投影定義一個monad。monad類型類看起來像這樣:
trait Monad[M[_]] { def point[A](a: A): M[A] def bind[A, B](m: M[A])(f: A => M[B]): M[B]}
現(xiàn)在,要么是兩個參數(shù)的類型構造函數(shù),但要實現(xiàn)Monad,您需要為它提供一個參數(shù)的類型構造函數(shù)。對此的解決方案是使用類型lambda:
class EitherMonad[A] extends Monad[({type λ[α] = Either[A, α]})#λ] { def point[B](b: B): Either[A, B] def bind[B, C](m: Either[A, B])(f: B => Either[A, C]): Either[A, C]}
這是在類型系統(tǒng)中進行currying的一個示例 - 您已經(jīng)知道了Either的類型,這樣當您想要創(chuàng)建EitherMonad的實例時,您必須指定其中一種類型; 另一方面當然是在你調用point或bind時提供的。
類型lambda技巧利用了類型位置中的空塊創(chuàng)建匿名結構類型的事實。然后我們使用#語法來獲取一個類型成員。
在某些情況下,您可能需要更復雜的類型lambda,這是寫內(nèi)聯(lián)的痛苦。這是我今天的代碼中的一個例子:
// types X and E are defined in an enclosing scopeprivate[iteratee] class FG[F[_[_], _], G[_]] { type FGA[A] = F[G, A] type IterateeM[A] = IterateeT[X, E, FGA, A] }
這個類專門存在,所以我可以使用像FG [F,G] #IterateeM這樣的名稱來引用IterateeT monad的類型,專門用于第二個monad的某些變換器版本,專門用于某些第三個monad。當你開始堆疊時,這些類型的構造變得非常必要。當然,我從未實例化過FG; 它只是作為一個黑客讓我在類型系統(tǒng)中表達我想要的東西。

TA貢獻1829條經(jīng)驗 獲得超9個贊
其好處與匿名函數(shù)賦予的好處完全相同。
def inc(a: Int) = a + 1; List(1, 2, 3).map(inc)List(1, 2, 3).map(a => a + 1)
使用Scalaz 7的一個示例用法。我們想要使用一個Functor
可以在一個函數(shù)中映射第二個元素的函數(shù)Tuple2
。
type IntTuple[+A]=(Int, A)Functor[IntTuple].map((1, 2))(a => a + 1)) // (1, 3)Functor[({type l[a] = (Int, a)})#l].map((1, 2))(a => a + 1)) // (1, 3)
Scalaz提供了一些可以推斷類型參數(shù)的隱式轉換Functor
,因此我們經(jīng)常避免完全編寫這些轉換。上一行可以重寫為:
(1, 2).map(a => a + 1) // (1, 3)
如果使用IntelliJ,則可以啟用“設置”,“代碼樣式”,“Scala”,“折疊”,“鍵入Lambdas”。然后,這隱藏了語法的苛刻部分,并呈現(xiàn)更可口:
Functor[[a]=(Int, a)].map((1, 2))(a => a + 1)) // (1, 3)
Scala的未來版本可能直接支持這種語法。
添加回答
舉報