Haskell 如何解释GHCI报告的类型

Haskell 如何解释GHCI报告的类型,haskell,ghc,ghci,Haskell,Ghc,Ghci,当要求GHCI输入一个类型时,我倾向于远离理想的类型(例如,不完全是要放入函数签名的内容,或者在语法上与库组合符的文档类型相似) 为什么GHCI显示一个隐藏的内部类型(甚至是包版本),但在第二种情况下,当包(可能)设计为使用别名时,它是一个通用类型 基本上避免使用非平凡类型的类型推断器和查找文档,这是一种好的做法吗 一个更“流行”的库示例: *Main Control.Lens> :t _2 _2 :: (Functor f, Field2 s t a b) => (a ->

当要求
GHCI
输入一个类型时,我倾向于远离理想的类型(例如,不完全是要放入函数签名的内容,或者在语法上与库组合符的文档类型相似)

为什么
GHCI
显示一个隐藏的内部类型(甚至是包版本),但在第二种情况下,当包(可能)设计为使用别名时,它是一个通用类型

基本上避免使用非平凡类型的类型推断器和查找文档,这是一种好的做法吗

一个更“流行”的库示例:

*Main Control.Lens> :t _2
_2 :: (Functor f, Field2 s t a b) => (a -> f b) -> s -> f t
*Main Control.Lens> :t over
over :: Profunctor p => Setting p s t a b -> p a b -> s -> t
*Main Control.Lens> :t over _2
over _2 :: Field2 s t a b => (a -> b) -> s -> t

ghci如何描述该类型取决于:

  • 引用的模块是否在范围内
  • 参考包是你的阴谋集团项目的一部分吗
  • 在这种情况下,您将看到一个内部类型,而不是预期的导出类型:

    === file B.hs ===
    
    module B (hello) where
    import Data.Text
    hello = pack "Hello, world"
    
    === file A.hs ===
    module A where
    import B
    
    然后运行
    ghci A.hs
    ,命令
    :t hello
    将报告:

    ghci> :t hello
    hello :: Data.Text.Internal.Text
    
    但是,如果模块A导入数据。文本:

    module A where
    import B
    import Data.Text
    
    然后,ghci通过以下方式响应类型查询:

    ghci> :t hello
    hello :: Text
    
    对于类型名称中出现的特定包名,如果在cabal文件中没有明确提到
    text
    作为依赖项,但您从另一个包导入了Data.text值,则可能会出现这种情况

    例如,假设上面的模块B是
    hello
    包的一部分,而模块A是单独包的一部分,比如说
    使用hello

    假设
    使用hello.cabal
    文件如下所示:

    === file uses-hello.cabal ===
    ...
    library:
      exposed-modules: A
      build-depends: base, hello
    ...
    
    请注意,
    使用hello
    不会将
    文本
    列为包依赖项,但它可以通过从
    hello
    包导入
    B
    来使用文本值。如果在
    使用hello
    包中运行
    cabal repl
    ,您将得到如下输出:

    $ cabal repl
    *A> :t hello
    hello :: text-1.2.1.1:Data.Text.Internal.Text
    

    ghci如何描述该类型取决于:

  • 引用的模块是否在范围内
  • 参考包是你的阴谋集团项目的一部分吗
  • 在这种情况下,您将看到一个内部类型,而不是预期的导出类型:

    === file B.hs ===
    
    module B (hello) where
    import Data.Text
    hello = pack "Hello, world"
    
    === file A.hs ===
    module A where
    import B
    
    然后运行
    ghci A.hs
    ,命令
    :t hello
    将报告:

    ghci> :t hello
    hello :: Data.Text.Internal.Text
    
    但是,如果模块A导入数据。文本:

    module A where
    import B
    import Data.Text
    
    然后,ghci通过以下方式响应类型查询:

    ghci> :t hello
    hello :: Text
    
    对于类型名称中出现的特定包名,如果在cabal文件中没有明确提到
    text
    作为依赖项,但您从另一个包导入了Data.text值,则可能会出现这种情况

    例如,假设上面的模块B是
    hello
    包的一部分,而模块A是单独包的一部分,比如说
    使用hello

    假设
    使用hello.cabal
    文件如下所示:

    === file uses-hello.cabal ===
    ...
    library:
      exposed-modules: A
      build-depends: base, hello
    ...
    
    请注意,
    使用hello
    不会将
    文本
    列为包依赖项,但它可以通过从
    hello
    包导入
    B
    来使用文本值。如果在
    使用hello
    包中运行
    cabal repl
    ,您将得到如下输出:

    $ cabal repl
    *A> :t hello
    hello :: text-1.2.1.1:Data.Text.Internal.Text
    

    lens
    在这方面可能不好,它的文档通常会列出几种简单的替代类型,以提供直观性。除了查看文档之外,我的技巧是使用
    :i
    而不是
    :t
    作为库标识符,然后您会得到实际的书面类型签名,有时扩展性较小。是的,
    lens
    中的大多数内容尤其容易理解为“你可以选择这是这个类型家族中的任何一个”,而不是试图统一所有类型的“真实”类型。非信息性的
    :类型
    结果只是你必须接受才能使用
    镜头
    ,除非/直到你真正学到更多支撑其结构的理论(否则就没有必要有效地使用它)。关于“基本上避免使用非琐碎类型和查找文档的类型推断器是一种好的做法吗?”,这不是一个“好的做法”的问题。我希望大多数人使用当时更有用/方便的方法,而不用担心任何一种方法“更好”“。我在开发过程中经常使用解释器,因此,如果我碰巧有一个ghci会话正在进行,我通常会从
    :t
    开始。如果这没有帮助(可能是因为类型令人困惑,但通常是因为类型本身并不能完整地描述事物的功能),我查找文档。
    lens
    对此可能不好,它的文档通常会列出几种更简单的类型,以提供直观性。除了查看文档之外,我的建议是使用
    :I
    而不是
    :t
    作为库标识符,然后您会得到实际的书面类型签名,有时是较少扩展。是的,
    lens
    中的大多数内容更容易理解为“你可以选择这类类型中的任何一种”,而不是“真实的”类型能够统一所有的类型。无信息的
    :类型
    结果只是你必须接受才能使用
    镜头
    ,除非/直到你真正学到更多支撑其结构的理论(否则没有必要有效地使用它)。关于“基本上避免使用非平凡类型和查找文档的类型推断器是一种好做法吗?”,这不是一个“好做法”的问题。我希望大多数人使用当时更有用/更方便的方法,而不用担心任何一种方法“更好”“。我在开发过程中经常使用解释器,因此如果我碰巧有一个ghci会话进行,我通常会从
    :t
    开始。如果这没有帮助(可能是因为类型令人困惑,但通常是因为类型本身并不能完整地描述事物的功能),我会查找文档。