我一直在深入了解 haskell 类型系统的本质,并试图了解类型类的要点。我已经学到了很多东西,但我在下面的代码片段上遇到了困难。
使用这些类和实例定义:
class Show a => C a where
f :: Int -> a
instance C Integer where
f x = 1
instance C Char where
f x = if x < 10 then 'c' else 'd'
为什么这会通过类型检查器:
g :: C a => a -> Int -> a
g x y = f y
yes :: C a => a -> Int -> String
yes x y = show (g x y)
但这不是吗?
g :: C a => a -> Int -> String
g x y = show(f y)
我发现第二种选择更具可读性,而且似乎只有很小的区别(注意类型签名)。然而,试图通过类型检查器会导致:
*Main> :l typetests.hs
[1 of 1] Compiling Main ( typetests.hs, interpreted )
typetests.hs:11:14:
Ambiguous type variable `a0' in the constraints:
(C a0) arising from a use of `f' at typetests.hs:11:14
(Show a0) arising from a use of `show' at typetests.hs:11:9-12
Probable fix: add a type signature that fixes these type variable(s)
In the first argument of `show', namely `(f y)'
In the expression: show (f y)
In an equation for `g': g x y = show (f y)
Failed, modules loaded: none.
我不明白为什么。
注意:请不要问“你想做什么?”我希望很明显我只是在抽象上下文中闲逛,以便探索这种语言的工作方式。除了学习新东西之外,我没有其他目标。
Thanks
这就是一个有趣的玩具发挥作用的地方。考虑标准 Prelude 函数asTypeOf
.
asTypeOf :: a -> a -> a
asTypeOf = const
它只返回第一个参数,无论第二个参数是什么。但它的类型签名施加了额外的约束,即它的两个参数必须是相同的类型。
g :: C a => a -> Int -> String
g x y = show (f y `asTypeOf` x)
现在,GHC 知道什么类型f y
是。它与第一个参数的类型相同g
。如果没有这些信息,您就会收到所看到的错误消息。只是没有足够的信息来确定类型f y
。因为类型很重要(它用于确定要使用哪个实例)show
),GHC 需要知道你想要生成代码的类型。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)