繁体   English   中英

函数和非归纳类型

[英]Functors and Non-Inductive Types

我正在研究Typeclassopedia中的Functors部分

一个简单的直觉是Functor代表某种“容器”,以及将函数统一应用于容器中的每个元素的能力。

好。 因此,对于像列表或树这样的归纳类型,仿函数看起来非常自然。

如果元素的数量固定为较小的数字,Functors也会显得非常简单。 例如,使用Maybe你只需要关注“Nothing”或“Just a” - 两件事。

那么,你如何制作类似图形的东西,可能有循环,一个Functor的实例? 我认为更普遍的方式是,非归纳类型如何“适应”Functors?


我越是想到它,我就越意识到归纳/非归纳并不重要。 归纳类型更容易定义fmap ...

如果我想将图形作为Functor的一个实例,我将不得不在fmap中实现图形遍历算法; 例如,它可能必须使用一个辅助函数来跟踪被访问的节点。 在这一点上,我现在想知道为什么还要把它定义为Functor而不仅仅是把它作为一个函数本身? 例如地图vs fmap列表......?

我希望有经验,有战争故事和伤疤的人可以解释一下。 谢谢!

好吧,假设您定义了这样的图形

data Graph a = Node a [Graph a]

然后fmap就像你期望的那样精确定义

instance Functor Graph where
  fmap f (Node a ns) = Node (f a) (map (fmap f) ns)

现在,如果有一个循环,那么我们不得不做类似的事情

foo = Node 1 [bar]
bar = Node 2 [foo]

现在fmap非常懒惰,你可以在不强制计算其余部分的情况下评估其部分结果,因此它的效果与任何结关联的图形表示一样好!

一般来说这就是诀窍: fmap是懒惰的,所以你可以像处理Haskell中的任何非归纳值一样处理它的结果(:仔细)。

此外,您应该定义fmap与随机的其他函数

  1. fmap是一个很好的,众所周知的API和规则
  2. 现在,您的容器可以很好地满足Functor的需求
  3. 你可以抽象出程序的其他部分,这样它们就依赖于Functor ,而不是你的Graph

一般来说,当我看到某些东西是仿函数时,我觉得“很好,我知道如何使用它”,当我看到时

superAwesomeTraversal :: (a -> b) -> Foo a -> Foo b

我有点担心这会做出意想不到的事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM