簡體   English   中英

使用折疊在樹上實現地圖

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM