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