从上下文中猜测 Num 的正确实例
Guessing the correct instance of Num from the context
假设:
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
会导致错误(No instance for (Num a0) arising from the literal '1')因为 1
是 Num a => a
并且编译器不知道 [=17= 的哪个实例] 应该是。
但是,(逻辑上)应该可以推断出 1
是一个 Int64
,因为它被传递给 meh
而 meh
只能接受一个Int64
或 Unknown
。换句话说,应该可以计算Num
和Meh
的"intersection"并决定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:
Type-类 已打开。没有人限制别人定义:
newtype MyInt = MyInt Int deriving (Num)
instance Meh MyInt where
meh = ...
那么即使在你的例子中meh 1
也可以解析为(meh :: Int64 -> String) 1
,一般情况下是不行的。 "but based on the Meh
instances visible in the scope" 之类的参数在 Haskell 中实际上不起作用,因为实例是全局的。
如果您定义 data
(已关闭),则使用 {-# LANGUAGE OverloadedStrings #-}
您可以:
data Meh = MehInt Int64 | MehString String
instance IsString Meh where
fromString = MehString
然后
"foo" :: Meh
将编译为 GHC "will see"
fromString "foo" :: Meh
同样,您可以定义不完整的 Num
实例,仅定义 fromInteger
。然而,我个人不喜欢不完整的实例,尽管这种情况在定义 eDSL 时很方便。
假设:
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
会导致错误(No instance for (Num a0) arising from the literal '1')因为 1
是 Num a => a
并且编译器不知道 [=17= 的哪个实例] 应该是。
但是,(逻辑上)应该可以推断出 1
是一个 Int64
,因为它被传递给 meh
而 meh
只能接受一个Int64
或 Unknown
。换句话说,应该可以计算Num
和Meh
的"intersection"并决定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:
Type-类 已打开。没有人限制别人定义:
newtype MyInt = MyInt Int deriving (Num)
instance Meh MyInt where
meh = ...
那么即使在你的例子中meh 1
也可以解析为(meh :: Int64 -> String) 1
,一般情况下是不行的。 "but based on the Meh
instances visible in the scope" 之类的参数在 Haskell 中实际上不起作用,因为实例是全局的。
如果您定义 data
(已关闭),则使用 {-# LANGUAGE OverloadedStrings #-}
您可以:
data Meh = MehInt Int64 | MehString String
instance IsString Meh where
fromString = MehString
然后
"foo" :: Meh
将编译为 GHC "will see"
fromString "foo" :: Meh
同样,您可以定义不完整的 Num
实例,仅定义 fromInteger
。然而,我个人不喜欢不完整的实例,尽管这种情况在定义 eDSL 时很方便。