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



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

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

(x->x+1) id :: Num (a -> a) => a -> a

第一个例子是

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

现在棘手的一点是函数类型有一个Monad实例。

instance Monad ((->) r) where
    return = const
    f >>= k =  r -> k (f r) r

因此,可以在期望传递Monad a => m a的地方传递r -> a类型的函数。由于id :: a -> a,我们得到r=a, m a = a -> am 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)

这里假设(fromininteger 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

最新更新