我对考试有点不满。我想通过手工应用统一算法来找出这两个函数的类型:
map map
(\x -> x >>= (\y -> y))
有人能指出我正确的方向吗?到目前为止我唯一能找到的资源是维基百科条目,由于抽象程度很高,它并没有真正帮助我。
问候并谢谢你。
答案 0 :(得分:5)
我们先做第一个。
map :: (a -> b) -> [a] -> [b]
现在我们可以用两个不同的名称再次写它,为清楚起见:
map :: (c -> d) -> [c] -> [d]
现在我们将第二个替换为第一个参数,得到:
(a -> b) === (c -> d) -> ([c] -> [d]) (recall the associativity of (->))
a === (c -> d)
b === ([c] -> [d])
现在我们将这些类型分配替换为第一个签名的剩余部分,获取
map map :: [c -> d] -> [[c] -> [d]]
清除?
答案 1 :(得分:1)
map
的类型为map :: (a -> b) -> [a] -> [b]
。因此,map foo
的类型是通过将[a] -> [b]
和a
替换为可以从b
类型派生的内容而从foo
获得的。例如,如果foo :: t -> t
,则替换a = t, b = t
并获取[t] -> [t]
。如果foo :: [t] -> Int
,则获得[[t]] -> [Int]
。
在您的情况下,foo
(map
)的类型为(x -> y) -> [x] -> [y]
。您必须将该类型与a -> b
统一,以找出a
和b
必须替换的内容。 [请注意,函数箭头是右关联的,x -> y -> z = x -> (y -> z)
。]
找到
的类型\x -> x >>= (\y -> y)
使用已知类型的(>>=) :: Monad m => m a -> (a -> m b) -> m b
。暂时忽略约束(Monad m =>
)。
作为(>>=)
的第一个参数,x
必须包含m a
类型,但尚未知道m
和a
。 (>>=)
的第二个参数是身份,
(\y -> y) :: t -> t
因此您必须将t -> t
与a -> m b
统一起来。这会为您提供有关a
的一些信息,即a = m b
。
这会产生x :: m (m b)
和(\x -> x >>= (\y -> y)) :: type_of_x -> type_of_rhs
。
最后记住暂时忘记的约束Monad m =>
。