【问题标题】:Type-class instance discoverability - how to search?类型类实例可发现性 - 如何搜索?
【发布时间】:2014-09-24 09:28:43
【问题描述】:

示例 - Data.List 有一个为 Data.Foldable 定义的实例,但它是在可折叠而不是在列表中定义的(并且针对“[]”而不是“列表”)。

对于实例与类型本身在同一文件中定义的情况(例如Data.Sequence),它会在文档中列出。例如,我对 Hoogle 或 Hayoo 没有任何运气。

虽然我可以看到最常见的情况是带有数据类型定义的实例定义,但有时必须将其放在单独的文件中。我只是碰巧选择了一个不好的 Data.List 示例,还是我的搜索技能缺少某些东西?


澄清:我已经了解了可折叠和列表,并且可以合理地期望每个人在探索 Haskell 的早期就遇到过这两种情况。但是,对于某些复杂类型 T 来自例如Snap/Yesod/lens 我不太可能知道我从未遇到过的一些更复杂的类型类是相关的。我想知道是否有某种方法可以显式搜索未在类型文件中定义的实例(可以在类型的自动生成的文档中找到)。

【问题讨论】:

  • AFAIK Data.List 实现了[](及其功能),它是Prelude 的一部分,但Foldable 不是Prelude 的一部分不是 .将Foldable 的实例添加到Prelude 将添加对外部包的非必需依赖项,这不是一个好主意。 Prelude 应该能够在没有任何依赖的情况下工作。因此,这些实例被放在定义类的文件中。
  • @Bakuriu 实际上,它不依赖于外部包 - Data.Foldablebase 中。实际上,GHC 7.10 正在从 Prelude 导出 FoldableTraversable

标签: haskell


【解决方案1】:

反对“[]”而不是“列表”

嗯...没有像List这样的类型(至少not in the standard library)!

Haskell 实例可以在类模块中定义,也可以在数据类型模块中定义(或者实际上在其他任何地方,尽管这样的孤儿实例 是相当避免的)。选择取决于哪个模块更“基本”:更古怪的模块将取决于更标准的模块,并且只有当类和类型都在范围内时才能定义实例。正如[] 一直是Haskell 的基础之一,而Foldable 更多的是用于更高级的泛型编程的特定接口;所以很自然的只在Foldable模块中定义Foldable []实例。

查找实例定义位置的最简单工具是 GHCi。在你的例子中

Prelude> :m +Data.Foldable
Prelude Data.Foldable> :i 可折叠
可折叠类 (t :: * -> *) 其中
fold :: Data.Monoid.Monoid m => t m -> m
foldMap :: Data.Monoid.Monoid m => (a -> m) -> t a -> m
Data.Foldable.foldr :: (a -> b -> b) -> b -> t a -> b
foldr' :: (a -> b -> b) -> b -> t a -> b
Data.Foldable.foldl :: (b -> a -> b) -> b -> t a -> b
foldl' :: (b -> a -> b) -> b -> t a -> b
Data.Foldable.foldr1 :: (a -> a -> a) -> t a -> a
Data.Foldable.foldl1 :: (a -> a -> a) -> t a -> a
-- 在“Data.Foldable”中定义
instance Foldable [] -- 在‘Data.Foldable’中定义
实例 Foldable Maybe -- 在“Data.Foldable”中定义
可折叠实例(任一)--在“Data.Foldable”中定义
instance Foldable ((,) a) -- 在‘Data.Foldable’中定义

反之亦然:

Prelude Data.Foldable> :i []
数据 [] a = [] | a : [a] -- 在‘GHC.Types’中定义
instance Eq a => Eq [a] -- 在‘GHC.Classes’中定义
实例 Monad [] -- 在“GHC.Base”中定义
instance Functor [] -- 在‘GHC.Base’中定义
instance Ord a => Ord [a] -- 在‘GHC.Classes’中定义
instance Read a => Read [a] -- 在‘GHC.Read’中定义
instance Show a => Show [a] -- 在‘GHC.Show’中定义
instance Foldable [] -- 在‘Data.Foldable’中定义

现在,这当然不会显示任何不在范围内的实例。它不应该:任何人都可以在恰好安装在您系统上的某个包中为他们自己的晦涩类型类定义实例;显示这些不会有帮助。但是如果你在一个更大的框架中并使用“标准导入”,你也会得到所有的“标准实例,比如

Prelude Yesod> :i Html
输入 Html = Text.Blaze.Internal.Markup
-- 在“Text.Blaze.Html”中定义
Prelude Yesod> :i Text.Blaze.Internal.Markup
键入 Text.Blaze.Internal.Markup = Text.Blaze.Internal.MarkupM ()
-- 在‘Text.Blaze.Internal’中定义
Prelude Yesod> :i Text.Blaze.Internal.MarkupM
键入角色 Text.Blaze.Internal.MarkupM 幻像
数据 Text.Blaze.Internal.MarkupM 一个 where
Text.Blaze.Internal.Parent :: Text.Blaze.Internal.StaticString -> Text.Blaze.Internal.StaticString -> Text.Blaze.Internal.StaticString -> (Text.Blaze.Internal.MarkupM
b) -> Text.Blaze.Internal.MarkupM
一个
Text.Blaze.Internal.CustomParent :: Text.Blaze.Internal.ChoiceString -> (Text.Blaze.Internal.MarkupM
b) -> Text.Blaze.Internal.MarkupM
一个
Text.Blaze.Internal.Leaf :: Text.Blaze.Internal.StaticString -> Text.Blaze.Internal.StaticString -> Text.Blaze.Internal.StaticString -> Text.Blaze.Internal.MarkupM
一个
Text.Blaze.Internal.CustomLeaf :: Text.Blaze.Internal.ChoiceString -> Bool -> Text.Blaze.Internal.MarkupM
一个
Text.Blaze.Internal.Content :: Text.Blaze.Internal.ChoiceString -> Text.Blaze.Internal.MarkupM
一个
Text.Blaze.Internal.Append :: (Text.Blaze.Internal.MarkupM
b) -> (Text.Blaze.Internal.MarkupM
c) -> Text.Blaze.Internal.MarkupM a
Text.Blaze.Internal.AddAttribute :: Text.Blaze.Internal.StaticString -> Text.Blaze.Internal.StaticString -> Text.Blaze.Internal.ChoiceString -> (Text.Blaze.Internal.MarkupM
a) -> Text.Blaze.Internal.MarkupM
一个
Text.Blaze.Internal.AddCustomAttribute :: Text.Blaze.Internal.ChoiceString -> Text.Blaze.Internal.ChoiceString -> (Text.Blaze.Internal.MarkupM
a) -> Text.Blaze.Internal.MarkupM
一个
Text.Blaze.Internal.Empty :: Text.Blaze.Internal.MarkupM a
-- 在“Text.Blaze.Internal”中定义
实例 Monad Text.Blaze.Internal.MarkupM
-- 在“Text.Blaze.Internal”中定义
实例 Functor Text.Blaze.Internal.MarkupM
-- 在“Text.Blaze.Internal”中定义
实例 ToWidgetHead 站点 Html -- 在“Yesod.Core.Widget”中定义
实例渲染 ~ Yesod.Core.Types.RY 站点 =>
ToWidgetHead 网站(呈现 -> Html)
-- 在‘Yesod.Core.Widget’中定义
实例 ToWidgetBody 站点 Html -- 在“Yesod.Core.Widget”中定义
实例渲染 ~ Yesod.Core.Types.RY 站点 =>
ToWidgetBody 网站(呈现 -> Html)
-- 在‘Yesod.Core.Widget’中定义
实例 ToWidget 站点 Html -- 定义在 ‘Yesod.Core.Widget’
实例渲染 ~ Yesod.Core.Types.RY 站点 =>
ToWidget 网站(渲染 -> Html)
-- 在‘Yesod.Core.Widget’中定义
实例 ToTypedContent Html -- 在“Yesod.Core.Content”中定义
实例 ToFlushBuilder Html -- 在“Yesod.Core.Content”中定义
实例 ToContent Html -- 在“Yesod.Core.Content”中定义
实例 HasContentType Html -- 在‘Yesod.Core.Content’中定义
实例 [重叠 ok] PersistField Html
-- 在‘persistent-1.3.3:Database.Persist.Class.PersistField’中定义

【讨论】:

  • 好的,谢谢。所以基本上我可以依靠使用 ghci 的“正确的东西”(一旦我安装了库)。
猜你喜欢
  • 1970-01-01
  • 2012-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-11
  • 1970-01-01
  • 2011-03-10
  • 1970-01-01
相关资源
最近更新 更多