[英]Implementing map on a tree using fold
我正在嘗試使用fold實現地圖。 我可以在Haskell這樣做
data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show)
foldTree :: Tree a -> b -> (b -> a -> b -> b) -> b
foldTree EmptyTree d _ = d
foldTree (Node a l r) d f = f (foldTree l d f) a (foldTree r d f)
mapTree :: Tree a -> ( a -> b) -> Tree b
mapTree tree f = foldTree tree EmptyTree (\l n r -> Node (f n) l r)
但是,當我嘗試將其移植到Scala時,我有點卡住了
sealed trait Tree[+A]
case object EmptyTree extends Tree[Nothing]
case class Node[A](value: A , left: Tree[A], right: Tree[A]) extends Tree[A]
def fold[A, B](t:Tree[A] , z:B)(f:(B,A,B) => B) : B = t match {
case EmptyTree => z
case Node(x,l,r) => f ( fold( l , z )(f) , x , fold( r , z )(f) )
}
def map(tree:Tree[Int])(f:Int=>Int) : Tree[Int] = fold(tree , EmptyTree)((l,x,r) => Node(f(x),l,r))
編譯器抱怨說我希望傳遞給函數的EmptyTree可以折疊。
fold(tree , EmptyTree)((l,x,r) => Node(f(x),l,r))
Map的返回類型是Tree,所以我希望它能正常工作。 有什么建議么 ?
嘗試將您的最后一行寫為
def map(tree:Tree[Int])(f:Int=>Int) : Tree[Int] = fold(tree , EmptyTree:Tree[Int])((l,x,r) => Node(f(x),l,r))
與haskell相比,Scala的類型推斷非常有限,在這種情況下,它試圖從其參數從左到右推斷出fold
類型,並且錯誤地確定折疊的結果類型應為EmptyTree
而不是Tree[Int]
。 通常將輔助構造函數添加到父類型的伴隨對象中會對此有所幫助,例如,在Option對象中有一個構造函數
def empty[A]: Option[A]
返回父類型。
作為@vitalii解決方案的替代方法,使類型參數fold
顯式:
def map(tree: Tree[Int])(f: Int=>Int): Tree[Int] =
fold[Int, Tree[Int]](tree, EmptyTree)((l, x, r) => Node[Int](f(x), l, r))
// ^^^^^^^^^^^^^^
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.