当我在GHCi中输入:t
命令时,我看到多态类型:
ghci> :t 42
42 :: Num t => t
ghci> :t div
div :: Integral a => a -> a -> a
但在我实际评估这些函数后,我看到了类型默认规则的结果。是否有一些命令或能力在ghci中观察在根据Haskell报告和/或ghc实现应用类型默认规则后如何更改类型?
答案 0 :(得分:5)
您可以通过启用单态限制然后将其绑定到新名称来执行此操作:
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 -XMonomorphismRestriction\nlet defaulted = "++e++"\n:t defaulted")
(您可能希望将其放在.ghci
文件中以始终使用该命令)然后
Prelude> :monotype (^)
defaulted :: Integer -> Integer -> Integer
当然,启用单态限制的隐藏的全局副作用非常难看,但是很好......
答案 1 :(得分:4)
不是一个完美的解决方案,但它可能是第一步。
> import Data.Typeable
> let withType x = (x, typeOf x)
> withType []
([],[()])
> withType 56
(56,Integer)
请注意,由于类型a
已更改为(a,TypeRep)
,因此GHCi不会使用其所有默认魔法。不过,其中一些可以展示出来。
GHCi的:set +t
选项也很有意思,但似乎在GHCi默认之前打印出多态类型。
答案 2 :(得分:2)
从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
答案 3 :(得分:1)
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元素)列表的633825300114114700748351602688元素。因为表达式2^100 `div` 2
被用作!!
的自变量(通过n
绑定在非本地),并且(!!) :: [a] -> Int -> a
的类型为Int
选择为Integer
,而不是在没有此上下文的情况下默认选择的类型(Int
)。将表达式评估为:t +d
会有不同的结果(由于溢出,为0)。
这意味着当您为GHC中的类型错误抓狂,并在GHCi中使用for($i=0;$i<5;$i++){
$arr1['a'] = $i;
$arr1['b'] = $i+=2;
$arr2[] = $arr; //assign the arr1 into the arr2
$arr1= []; //clear arr1 again for the next looping
}
var_dump($arr2);
尝试获取更多信息时,您需要注意,可能仍然看不到相同的内容GHC实际使用的类型。保证多态类型与所使用的一种GHC兼容,但是在任何其他上下文中将其默认设置可能会导致另一种不兼容。