如何解释GHCI报告的类型

时间:2015-10-13 20:56:25

标签: haskell ghc ghci

当问GHCI类型时,我倾向于远离理想类型(例如,不完全是放入我的函数签名或在语法上类似于库组合器的类型)。

*Main Control.Monad.Shell> :t script
script :: Script f -> text-1.2.1.3:Data.Text.Internal.Lazy.Text

*Main Control.Monad.Shell> :t cmd "echo" "foo"
cmd "echo" "foo" :: CmdParams t => t

为什么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

1 个答案:

答案 0 :(得分:4)

ghci如何描述类型取决于:

  1. 引用的模块是否在范围内?
  2. 引用的包是您的cabal项目的一部分吗?
  3. 在这种情况下,您将看到内部类型而不是预期的导出类型:

    === 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导入Data.Text:

    module A where
    import B
    import Data.Text
    

    然后ghci响应类型查询:

    ghci> :t hello
    hello :: Text
    

    对于出现在类型名称中的特定包名称,如果未在您的cabal文件中明确提及text作为依赖项,但是从另一个中导入Data.Text值,则可能会发生这种情况。封装

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

    让我们说uses-hello.cabal文件如下:

    === file uses-hello.cabal ===
    ...
    library:
      exposed-modules: A
      build-depends: base, hello
    ...
    

    请注意,uses-hello 列出text作为包依赖项,但它可以通过从{{1}导入B来使用Text值包。如果您在hello包中运行cabal repl,您将获得如下输出:

    uses-hello