认为:
import Data.Int (Int64)
data Unknown
class Meh a where
meh :: a -> String
instance Meh Int64 where
meh = show
instance Meh Unknown where
meh _ = "Unknown"
很明显,meh
只能取Int64
或Unknown
。
但是我们都知道
meh 1
会导致错误(原义'1'不会引起(Num a0)的实例),因为1
isNum a => a
并且编译器不知道Num
它应该是哪个实例。
但是,(从逻辑上)应该可以推断1
为an,Int64
因为它将传递给meh
,meh
并且只能采用anInt64
或an Unknown
。换句话说,应该有可能计算出的“交叉点”Num
和Meh
,并决定哪个实例1
是。
所以我的问题是:你知不知道这使得它可以写任何方式(编译器扩展,代码的解决办法,任何东西)meh 1
,其中1
被正确地推断是Int64
不添加类型签名或添加专门的功能呢?
在GHC 7.8.3中尝试您的示例时
>>> meh 1
我得到:
<interactive>:2:1:
No instance for (Meh a0) arising from a use of ‘meh’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Meh Unknown -- Defined at Meh.hs:9:10
instance Meh Int64 -- Defined at Meh.hs:7:10
In the expression: meh 1
In an equation for ‘it’: it = meh 1
<interactive>:2:5:
No instance for (Num a0) arising from the literal ‘1’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
...
这是因为编译器尝试进行类型检查:
>>> meh (fromInteger (1 :: Integer))
为此,您会收到类似的错误:
<interactive>:4:1:
No instance for (Meh a0) arising from a use of ‘meh’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Meh Unknown -- Defined at Meh.hs:9:10
instance Meh Int64 -- Defined at Meh.hs:7:10
In the expression: meh (fromInteger (1 :: Integer))
In an equation for ‘it’: it = meh (fromInteger (1 :: Integer))
<interactive>:4:6:
No instance for (Num a0) arising from a use of ‘fromInteger’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
类型类是开放的。没有人可以限制其他人定义:
newtype MyInt = MyInt Int deriving (Num)
instance Meh MyInt where
meh = ...
然后,即使在您的示例中meh 1
也可以将其解析为(meh :: Int64 -> String) 1
,但通常无法。Meh
由于实例是全局的,因此诸如“但基于作用域中可见的实例”之类的参数在Haskell中实际上不起作用。
如果定义data
(已关闭),则可以使用{-# LANGUAGE OverloadedStrings #-}
:
data Meh = MehInt Int64 | MehString String
instance IsString Meh where
fromString = MehString
然后
"foo" :: Meh
将按照GHC“将看到的”进行编译
fromString "foo" :: Meh
同样,您可以定义不完整的Num
实例,仅fromInteger
定义一个。但是我个人不喜欢不完整的实例,尽管这种情况在定义eDSL时很方便。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句