簡體   English   中英

為什么以下用於創建Tree的Foldable實例的haskell代碼導致無限遞歸?

[英]Why does the following haskell code for creating a Foldable instance of Tree result in infinite recursion?

我正在嘗試編寫以下創建的Tree類的Foldable實例:

data Tree a b = Tree b a [Tree a b]

但是我想對定義中的類型“ a”進行操作,因此我將包裝數據類型轉換為Tree中的類型:

data FlipTree a b = FlipTree (Tree b a)

現在編寫實際定義,我想到了以下內容:

instance Foldable (FlipTree a) where
  foldr f x (FlipTree (Tree _ s [])) = (f s x)
  foldr f x (FlipTree (Tree _ s children)) =
              let updated_x = (f s x)
                  tqs = (map (\n -> FlipTree n) children) in
              foldl (foldr f) updated_x tqs

但這會在調用foldr時導致無限遞歸。 我已經花了兩天的時間,仍無法弄清我做錯了什么?

這是指向代碼文件的 lpaste鏈接。 我盡可能地隔離了代碼。 這是另一個file1 ,可使用以下命令讀取該文件以運行代碼:

runghc code.hs 30000000.0 20000.0 <file1.txt

不是答案(無限循環的前提條件似乎並不正確),而是風格上的建議–評論時間太長。

首先,你可能想使這個newtype (沒有理由有懶惰的一個額外層)。

newtype FlipTree a b = FlipTree (Tree b a)

其次,對於一個更容易理解的解決方案,它傾向於使IMO更可取的是實現foldMap而不是foldr 它使語義更清晰。 有多種方法可以折疊此結構,最合理的方法似乎是

  foldMap f (FlipTree (Tree _ s [])) = f s
  foldMap f (FlipTree (Tree _ s children))
             = f s <> foldMap (foldMap f . FlipTree) children

其中,外部foldMap折疊在foldMap列表上,再次將foldMap用於FlipTree用作折疊映射。 現在,如果要手動將其轉換為等效的foldr ,則基本上只需要遍歷該參數。

  foldr f x (FlipTree (Tree _ s children))
             = f s . flip (foldr $ flip (foldr f) . FlipTree) children $ x

現在,可能該實例實際上並未提供所需的行為,所以請告訴我們您希望它如何表現!

原來定義是100%正確的。 不必要的行為是由其余的代碼引起的。 但是無論如何,都要感謝stackoverflow社區一直存在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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