当前位置: 首页 > 知识库问答 >
问题:

基于右Kan扩展的列表

帅银龙
2023-03-14

在Ralf Hinze的“程序优化的Kan扩展”中,有一个列表类型的定义,它是基于从单子类中的遗忘函子的右Kan扩展(第7.4节)。本文给出了如下Haskell实现:

newtype List a = Abstr {
  apply :: forall z . (Monoid z) => (a -> z) -> z
  } 

我能够定义通常的nil和cons构造函数:

nil :: List a
nil = Abstr (\f -> mempty)

cons :: a -> List a -> List a
cons x (Abstr app) = Abstr (\f -> mappend (f x) (app f))
instance Monoid (Maybe a) where
  mempty = Nothing
  mappend Nothing m = m
  mappend (Just a) m = Just a

head :: List a -> Maybe a
head (Abstr app) = app Just

共有1个答案

夏侯兴学
2023-03-14

在包fmlist中提供了将列表作为自由monoid的这种实现,其中说明了它的一些有趣的属性(与大多数列表实现不同,这些实现是右偏的,而这个实现是真正无偏的;您可以创建一个任意树,当然,尽管monoid定律迫使您将其视为平坦的,但在无限情况下,您仍然可以观察到一些差异。这几乎是Haskell的一个怪癖--通常是自由monoid)。它还有一个tail的实现,所以这是对您问题的某种回答(但请参见下面)。

对于这些类型的表示(不仅仅是这个特殊的表示,还包括所有r.(a->r->r)->r->r列表的),通常有些操作(例如追加)变得更容易,有些操作(例如zip和tail)变得更难。在不同的地方对此进行了一些讨论,例如,如何获取函数流的尾部

但是,仔细观察fmlist,它的解决方案非常不令人满意:它只是使用foldr将提供给它的良好平衡树转换为偏右列表,这允许它执行常规的列表操作,但丢失了单元体结构。“中无限”列表的尾部不再是“中无限”,它恰到好处--像常规列表一样无限。

应该可以想出一个聪明的monoid实例来计算尾部,同时尽可能少地干扰结构的其他部分,但显然不会马上想到一个。不过,我可以想出一个不聪明的“强力”解决方案:使用无效的monoid实例欺骗并将“列表”具体化为树,检查树,然后将其折叠起来,以便最终结果有效。下面是我的nonfree包和fmlist:

nail :: FM.FMList a -> FM.FMList a
nail (FM.FM k) = FM.FM $ \f -> foldMap f (nail' (k N))

nail' :: N a -> N a
nail' NEmpty = error "nail' NEmpty"
nail' (N x) = NEmpty
nail' (NAppend l r) =
  case normalize l of
    NEmpty -> nail' r
    N x -> r
    l' -> NAppend (nail' l') r

-- Normalize a tree so that the left side of a root NAppend isn't an empty
-- subtree of any shape. If the tree is infinite in a particular way, this
-- won't terminate, so in that sense taking the tail of a list can make it
-- slightly worse (but you were already in pretty bad shape as far as
-- operations on the left side are concerned, and this is a pathological case
-- anyway).
normalize :: N a -> N a
normalize (NAppend l r) =
  case normalize l of
    NEmpty -> normalize r
    l' -> NAppend l' r
normalize n = n

 类似资料:
  • 本文向大家介绍Dapper.NET 列表扩展,包括了Dapper.NET 列表扩展的使用技巧和注意事项,需要的朋友参考一下 示例 数据库查询中的一个常见情况IN (...)是在运行时在此处生成列表。大多数RDBMS对此没有一个很好的隐喻-并且没有通用的跨RDBMS解决方案。相反,dapper提供了一些温和的自动命令扩展。所需要的只是提供的参数值IEnumerable。涉及的命令@foo将扩展为(@

  • 'kan-java' is '砍-java', speak frankly & literally. 这是一个java代码动态编译工具,也就是能够把String形式的java代码实时地编译为字节码的工具; “动态编译”工具,其实自jdk1.6发布以来,应该出现过很多,不过kan-java的特点在于 —— 就像它的名字一样 —— 可以选择性地砍掉任意语言特性; 也就是说 —— 这是一个可以在动态编译

  • 是否会添加对Chrome扩展的mDNS api的支持?有没有办法获取有关此功能的时间线(或排除)的信息?Chrome有一个用于Chrome应用程序的mDNS api,但不用于扩展。如果用户不必安装本机electron应用程序就可以发现我们的IOT类设备,这将对我的产品非常有帮助,因为Chrome应用程序正在停止用于Windows和OSX。

  • 注:内容翻译自官网参考文档中 Java Generated Code 的 Extensions 一节。 假设有一个消息带有扩展范围: message Foo { extensions 100 to 199; } protocol buffer编译器将让 Foo 继承 GeneratedMessage.ExtendableMessage 而不是通常的 GeneratedMessage. 类型的,

  • 本文向大家介绍C#扩展抽象基类,包括了C#扩展抽象基类的使用技巧和注意事项,需要的朋友参考一下 示例 与接口(可以描述为实现合同)不同,抽象类充当扩展的合同。 抽象类无法实例化,必须对其进行扩展,然后可以实例化生成的类(或派生类)。 抽象类用于提供通用实现 上面的示例显示了实现Car的任何扩展类如何自动接收HonkHorn方法。这意味着任何开发新汽车的开发人员都无需担心它将如何鸣笛。

  • 问题内容: 我想将一个字符串添加到列表中: 但它打印。这是为什么? 问题答案: 该函数是就地函数,即它将对原始列表本身进行更改。来自文档 通过添加 给定 列表中的所有项目来扩展列表;等效于a [len(a):] =L。 因此,您无需将其重新分配回列表变量。 你可以做 然后当您打印时 更好的方法 如下所述使用是更好的方法。