我一直在努力理解下面关于类型推断的另一个例子,
min :: Ord a => a -> a -> a
ap :: Monad m => m (a -> b) -> m a -> m b
f :: Ord a => (a -> a) -> a -> a
f = ap min
f reverse "on" -- "no"
将f
应用于ap
时,min
的类型如何推断?我应该在哪里寻找关于Haskell中类型推断主题的一些实际参考?
答案 0 :(得分:3)
ap :: Monad m => m (a -> b) -> m a -> m b
min :: Ord a => a -> a -> a
-------------------------------------------------
ap min :: ?
由于min
是ap
的参数,这意味着我们需要找到unify这两种类型的方法:
Monad m => m (a -> b)
Ord a => a -> a -> a
要做到这一点,首先我们需要弄清楚Monad
实例(如果有)适用于此处。由于a -> a -> a
与a -> (a -> a)
相同,因此m
类型变量需要等同于(->) a
。 (请注意,Haskell也支持类型系统中的currying和section;就像(+) 1
是函数(+)
部分应用于参数1
一样,(->) a
是将类型构造函数(->)
部分应用于类型a
。)
所以我们改写为:
Monad m => m (a -> b)
Ord a => ((->) a) (a -> a)
这样可以很容易地看到我们需要在ap
类型中进行的替换:
m := Ord a => (->) a
a := Ord a => a
b := Ord a => a
但在我们继续之前,我们需要确定Monad
是否存在(->) a
实例,否则这是一个类型错误。但以下是标准Monad
实例之一,它将执行:
instance Monad ((->) r) where
return a = const a
fa >>= g = \r -> g (fa r) r
现在让我们进行替换:
ap :: Ord a => ((->) a) (a -> a) -> ((->) a) a -> ((->) a) a
min :: Ord a => a -> a -> a
--------------------------------------------------------
ap min :: ?
取消ap
中的类型:
ap :: Ord a => (a -> a -> a) -> (a -> a) -> a -> a
min :: Ord a => a -> a -> a
--------------------------------------------------------
ap min :: ?
现在很容易看到解决方案:
ap :: Ord a => (a -> a -> a) -> (a -> a) -> a -> a
min :: Ord a => a -> a -> a
--------------------------------------------------------
ap min :: Ord a => (a -> a) -> a -> a
答案 1 :(得分:2)
你的问题与统一的概念有关,统一的概念可以粗略地描述为找到受环境强加的约束的表达式类型的过程。 看看Stephen Diehl开发的这个优秀的课程/手册,
第5章到第8章描述了你要找的东西。