Haskell 如何推断liftM2(=)id和(\x->;x+;1)id的类型

Haskell 如何推断liftM2(=)id和(\x->;x+;1)id的类型,haskell,type-inference,Haskell,Type Inference,我在学习哈斯克尔。有人能解释一下这两种类型是如何推断的吗?Num(a->a)是什么意思 在第一种情况下,我们有 liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r (==) :: Eq a => a -> a -> Bool 通过设置a1=a和a2=a我们得到 liftM2 (==) :: (Eq a, Monad m) => m a -> m a ->

我在学习哈斯克尔。有人能解释一下这两种类型是如何推断的吗?Num(a->a)是什么意思


在第一种情况下,我们有

liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
(==) :: Eq a => a -> a -> Bool
通过设置
a1=a
a2=a
我们得到

liftM2 (==) :: (Eq a, Monad m) => m a -> m a -> m Bool
现在棘手的一点是有

因此,可以在预期a
Monad a=>ma
的位置传递类型为
r->a
的函数。由于
id::a->a
我们得到
r=a
ma=a->a
m Bool=a->Bool
,导致

liftM2 (==) id :: (Eq a) => (a -> a) -> (a -> Bool)

对于第二种类型,该类型签名的意思是函数类型
(a->a)
有一个Num实例

Haskell数值文本是多态的,
((\x->x+1)id)
实际上是以下内容的语法糖:

((\x -> x + (fromInteger 1)) id)
其中,通过β-还原

id + (fromInteger 1)
这假设(fromInteger 1)是一个函数,并且有一种方法可以将两个函数与
+
运算符相加。默认情况下,这是不可能的,但Haskell允许您定义函数的加法,如果您真的想要的话

{-# LANGUAGE FlexibleInstances #-}

instance Num (Int -> Int) where
  f + g = \x -> f x + g x
  f * g = \x -> f x * g x
  abs f = \x -> abs (f x)
  fromInteger n = \x -> fromInteger n
  signum f = error "not implemented"


f1 :: Int -> Int
f1 x = x + 1

f2 :: Int -> Int
f2 x = x + 2

f3 :: Int -> Int
f3 = f1 + f2

main = do
  print $ f3 0

(id+(fromInteger 1))0可能重复,编译器选择哪个(+)函数?如果选择f+g=\x->f x+g x,(从整数1)0将得到一个错误。顺便说一句,您有一个输入错误'liftM2(=)if',在我所做的示例中,我只为
Int->Int
定义了实例,因此您需要添加一些类型注释以正确引导Haskell,就像我在
f1+f2
示例中所做的那样,所有函数都被注释。如果您使用
((fromInteger 1)(0::Int))::Int
,那么它应该可以工作
id + (fromInteger 1)
{-# LANGUAGE FlexibleInstances #-}

instance Num (Int -> Int) where
  f + g = \x -> f x + g x
  f * g = \x -> f x * g x
  abs f = \x -> abs (f x)
  fromInteger n = \x -> fromInteger n
  signum f = error "not implemented"


f1 :: Int -> Int
f1 x = x + 1

f2 :: Int -> Int
f2 x = x + 2

f3 :: Int -> Int
f3 = f1 + f2

main = do
  print $ f3 0