【发布时间】:2015-04-30 23:48:13
【问题描述】:
如果我将玫瑰树定义为
data RTree = Node a [RTree a]
deriving(Show, Eq)
我将如何为它定义地图功能? map函数定义为
map_rose_tree :: (a -> b) -> RTree a -> RTree b
【问题讨论】:
如果我将玫瑰树定义为
data RTree = Node a [RTree a]
deriving(Show, Eq)
我将如何为它定义地图功能? map函数定义为
map_rose_tree :: (a -> b) -> RTree a -> RTree b
【问题讨论】:
最简单的方法是启用DeriveFunctor扩展和derive Functor:
{-# LANGUAGE DeriveFunctor #-}
data RTree a
= Node a [RTree a]
deriving (Show, Eq, Functor)
map_rose_tree = fmap
但如果您想自己定义实例,则需要在 RTree 构造函数上进行模式匹配:
instance Functor RTree where
fmap f (Node a children) = Node _ _
您必须自己填写两个_。如果你有足够新的 GHC 版本,你可以编译它并得到错误,告诉你漏洞的类型 (_) 以及你可以用来实现它的相关绑定。第一个洞很容易,第二个难度更大,但我向你保证,只有fmap、f、a 和children 可以解决。
【讨论】:
children :: [RTree a],你想得到[RTree b]。你有一个函数fmap :: (a -> b) -> RTree a -> RTree b 和f :: a -> b,所以fmap f :: RTree a -> RTree b。您如何将其应用于列表的每个元素?
[RTree a],是一个嵌套结构。外部列表[] 是函子,内部RTree as 也是函子。您想将as 一直映射到内部,2 层深。那么你会怎么做呢?你可以fmap 一个函数覆盖外部列表,对吗?这将使您可以访问内部RTree as。现在如果你映射的那个函数也调用fmap呢?