自(==) :: Eq a => a -> a -> Bool
起,我希望
a == b :: Eq a => Bool
-- assuming a :: forall a. a
-- derived type
但是(根据GHCi :t
)
a == b :: Bool
现在当然需要TypeApplications
,因此默认情况下不应该启用它,但是有LANGUAGE
选项可以启用此功能吗?
NoMonomorphismRestriction
不起作用。
编辑:由于您可能会说“嗯,GHC(i)在任何实际示例中都已经知道a
和b
的类型”,例如,您可以拥有{{1 }}。
编辑:似乎(5 == 5) :: (Num a, Eq a) => Bool
是不可能的,所以让我们假设类似a :: forall a. a
编辑:明确声明类型行之有效,所以问题实际上是“ GHC可以推断这种类型为多态吗”,所以我正在寻找类似x = 5 :: Num a => a
的东西。
答案 0 :(得分:4)
这与(==)
的类型有关:
(==) :: forall a. Eq a => a -> a -> Bool
(==)
接受四个参数,顺序:
a
(又称Type
)的类型*
,Eq a
类型的字典,a
的值。a
的值。通常,部分应用程序只能按顺序运行 ,并且不能显式传递字典参数。此外,类型参数只能在使用前引入。因此,当您编写a == b
时,这实际上意味着
(==) @_ @{dict} a b
推断出类型实参和字典实参,并且您得到类型Bool
的值。
您追求的类型与(==)
截然不同:
numLitEq
:: (forall a. (Num a, Eq a) => a)
-> (forall b. (Num b, Eq b) => b)
-> forall c. (Num c, Eq c) => Bool
numLitEq a b = (==) @c a b
但是,您不能完全这样写,因为无法将c
类型的变量纳入范围。最好的办法是
numLitEq
:: forall c.
(forall a. (Num a, Eq a) => a)
-> (forall b. (Num b, Eq b) => b)
-> (Num c, Eq c) => Bool
numLitEq a b = (==) @c a b
这并不比仅使用(==)
更好。
答案 1 :(得分:1)
实际上,这至少在GHC-8.2和8.3中有效。
GHCi, version 8.2.1: http://www.haskell.org/ghc/ :? for help
Prelude> :set -XRank2Types -XUnicodeSyntax
Prelude> let x, y :: ∀ a . a; (x,y) = (undefined,undefined)
Prelude> :set -XAllowAmbiguousTypes
Prelude> let p :: ∀ a . Eq a => Bool; p = x==y
Prelude> :set -XTypeApplications
Prelude> p @Int
*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries/base/GHC/Err.hs:79:14 in base:GHC.Err
undefined, called at <interactive>:3:36 in interactive:Ghci1
Prelude> p @(String -> Double)
<interactive>:11:1: error:
• No instance for (Eq (String -> Double)) arising from a use of ‘p’
(maybe you haven't applied a function to enough arguments?)
• In the expression: p @(String -> Double)
In an equation for ‘it’: it = p @(String -> Double)
答案 2 :(得分:1)
请注意,如果您只是问是否可以将3 == 5
和3
类型的表达式5
设为多态的,答案是肯定的。必须借助某些语言扩展来明确给出签名,但是以下定义是多态的:
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module ThreeFive where
eq35 :: forall a . (Num a, Eq a) => Bool
eq35 = (3 :: a) == 5
或者,您可以使用TypeApplications
:
eq35' :: forall a . (Num a, Eq a) => Bool
eq35' = (==) @a 3 5
现在,GHCi将eq35
的类型报告为Bool
,但这是一个谎言,您可以通过添加+v
标志来看到:>
> :type eq35
eq35 :: Bool
> :type +v eq35
eq35 :: (Num a, Eq a) => Bool
或通过证明:
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-- Holistic number are all equal
newtype Holistic = Holistic Int deriving (Num)
instance Eq Holistic where
_ == _ = True
main = do print (eq35 @Int)
print (eq35 @Holistic)
并运行此命令将打印False
和True
。
我没有看到任何形式的语言扩展组合,它们可以使GHC自动{em> 为3 == 5
推断比True
更通用的类型,而无需明确类型签名。同样,尽管多态x
和y
可能是这样,x == y
要么默认为单态类型,要么被拒绝,除非您使用上述显式签名。