如何在GHCI中使用应用类型默认规则打印多态性函数(或值)



当我在ghci中输入 :t命令时,我会看到多态性类型:

ghci> :t 42
42 :: Num t => t
ghci> :t div
div :: Integral a => a -> a -> a

但是在我实际评估了此类功能之后,我会看到类型默认规则的结果。是否有某些命令或能力可以在GHCI中观察到根据Haskell报告和/或GHC实现应用类型默认规则后将如何更改类型?

您可以通过打开单态限制,然后将其绑定到新名称:

来做到这一点:
Prelude> :set -XMonomorphismRestriction 
Prelude> let n = 42
Prelude> :t n
n :: Integer
Prelude> let p = (^)
Prelude> :t p
p :: Integer -> Integer -> Integer
Prelude> let e = (**)
Prelude> :t e
e :: Double -> Double -> Double
Prelude> let d = div
Prelude> :t d
d :: Integer -> Integer -> Integer

如果您不喜欢始终定义一个新变量,则可以使用

来解决此问题
Prelude> :def monotype (e -> return $ ":set -XMonomorphismRestrictionnlet defaulted = "++e++"n:t defaulted")

(您可能需要将其放在.ghci文件中,以始终具有可用的命令)然后

Prelude> :monotype (^)
defaulted :: Integer -> Integer -> Integer

当然,实现单态限制的隐藏全球副作用非常丑陋,但是哦,好吧...

不是一个完美的解决方案,但这可能是第一步。

> import Data.Typeable
> let withType x = (x, typeOf x)
> withType []
([],[()])
> withType 56
(56,Integer)

请注意,由于a类型已更改为(a,TypeRep),因此GHCI不会使用其所有默认魔法。不过,可以显示其中的一些。

GHCI的:set +t选项也很有趣,但是在GHCI违约之前打印了多态性类型,似乎。

由于GHC 8.4.1,可以使用:type +d(或简短的:t +d)选项打印表达式的类型,如果可能的话,默认类型变量。

ghci> :t 42
42 :: Num p => p
ghci> :t +d 42
42 :: Integer
ghci> :t div
div :: Integral a => a -> a -> a
ghci> :t +d div
div :: Integer -> Integer -> Integer

GHCI真的不可能给您与GHC相似的默认行为,这正是为什么单态限制(现在)在GHCI中被默认关闭的原因。

如 @Shersh的答案所示,您现在可以询问GHCI默认给定表达式的内容。

Prelude> :t 2^100 `div` 2
2^100 `div` 2 :: Integral a => a
Prelude> :t +d 2^100 `div` 2
2^100 `div` 2 :: Integer
Prelude> 2^100 `div` 2
633825300114114700748351602688

,但这不一定反映GHC对相同表达式的作用,因为GHC在完整模块的上下文中编译了表达式。GHC可以考虑表达式的所有使用,因为GHCI只能访问表达式的组成部分。GHC仅在考虑所有额外上下文之后默认含糊不清的事物,因此不能保证使用GHCI中:t +d看到的表达式的类型。

例如:

n = 2^100 `div` 2
xs = "ABCD"
main = print $ xs !! n

这是打印'A',显然不是该(4个元素)列表的6333825300114114114114114114114748351688TH。因为表达式 2^100 `div` 2使用的作为 !!的参数(非局部,通过 n绑定),而 (!!) :: [a] -> Int -> a类型是Int,而不是默认情况下选择的类型,而没有此上下文。(Integer)。评估该表达为Int的结果不同(0,由于溢出)。

这意味着,当您在GHC中的类型错误上划痕并在GHCI中使用:t +d来尝试获取更多信息时,您需要意识到您仍然可能没有看到与GHC相同的类型实际使用。保证多态类型与GHC使用的一个类型兼容,但是在任何其他上下文中默认情况下可能会导致不同的一种。

最新更新