foldr:: (a -> b -> b) -> b -> [a] -> b
map :: (a -> b) -> [a] -> [b]
mys :: a -> a
(.) :: (a -> b) -> (c -> a) -> c -> b
推断的类型是什么:
a.map mys ::
b.mys map ::
c.foldr map ::
d.foldr map.mys ::
我尝试使用mys n = n + 2创建mys,但其类型是
mys :: Num a => a -> a
'Num a =>之间有什么区别? a - > a'和'只是'a - >一个'?或者'Num a =>'是什么意思?难道mys只会采用Num类型吗?
所以无论如何,
a)我得到了[a] - > [a]我认为因为它只需要一个列表并根据我对mys的定义将其返回+ 2
b)(a - > b) - > [a] - > [b]我认为因为地图仍然需要带两个参数,如(* 3)和一个列表然后返回[a]进入mys并返回[b]
c)我不知道该怎么做1.
d)我不知道如何做到这一点1,但map.mys意味着先做mys然后映射到右边?
我的答案和想法是否正确?如果没有,为什么不呢?
谢谢!
答案 0 :(得分:3)
(更新:显然我的原始答案对OP没有太大帮助...请参阅下面的第二个HR作为附录。)
在这种情况下,您真正想要做的是启动ghci
并使用:t
找出各种表达式的类型。 E.g。
:t foldr map
-- answer: foldr map :: [b] -> [b -> b] -> [b]
如果您需要先定义名称,请使用let
(在Haskell源文件中不需要):
let mys = undefined :: a -> a
:t map mys
-- answer: [a] -> [a]
请注意undefined
使用显式类型签名。找到各种形式的表达式类型是完全可以的,甚至在实际代码中作为早期规划阶段的占位符也很有用。
Num a =>
是a
上的类型类约束;见例如Type Classes and Overloading来自“Haskell的温和介绍,版本98”或来自“真实世界Haskell”的Chapter 6. Using Typeclasses以获取更多信息。 (基本上,它做你认为它做的。: - ))
以上内容对于验证您的答案非常有用(类型类的资源也很好)。至于如何自己解决这类问题:
类型推断是所谓的“统一算法”的应用。谷歌为一些资源“统一”;如果您在查询中添加编程语言的名称,则可能会找到示例实现。
关于如何处理手边的例子......
一个。 map mys
:map
采用类型为a -> b
的函数,并返回类型为[a] -> [b]
的函数。通常,a
可能与b
不同,但mys
的类型为a -> a
,因此返回的函数的类型为[a] -> [a]
。
这是一些统一手:
(a -> b) -> [a] -> [b]`
(a -> a)`
^-- at this point we unify a with b;
when propagated to the return type,
this produces [a] -> [a]
湾mys map
:mys
是一个函数,它接受某种类型的对象并返回相同类型的对象。特别是,如果你传递一个(a -> b) -> [a] -> [b]
类型的参数,那将是返回值的类型。
顺便说一下,只有一个“有趣”(非undefined
)函数,其类型签名为a -> a
(没有类型类约束),即id
。请参阅Philip Wadler的论文“免费定理”。 (您可以从this page下载)进行扩展讨论。
℃。 foldr map
:首先,请注意a
签名中的b
和foldr
与map
签名中的map
和a
签名无关。将c
的{{1}}重命名为b
和d
重命名为map :: (c -> d) -> [c] -> [d]
并使用签名(a -> b -> b)
更方便明显如下。另请注意,(a -> (b -> b))
只是编写(a -> (b -> b))
(c -> d) -> [c] -> [d]
的简单方法。
更多的手统一(以下解释):
foldr
这里发生的是(a -> (b -> b))
采用类型为map
的函数参数。如果您传递a
作为该参数,则c -> d
与b
统一,[c]
与[d]
统一,然后再与c
统一,这意味着d
等于foldr
。
b -> [a] -> b
的返回值的类型为[c] -> [c -> c] -> [c]
^-- c equals d, right?
;替换前一段中获得的更具体的类型,我们得到
c
map
来自我们更改的b
签名;使用原始[b] -> [b -> b] -> [b]
,这变为
foldr map . mys
d。 (foldr map) . mys
:这实际上是foldr (map . mys)
,而不是{{1}} - 函数应用程序(“隐形运算符”)绑定最强!结合一个。和c。从上面解决这个问题留给读者作为练习。 ; - )