这是些ghci
> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
> :t allEqual
allEqual :: Eq a => [a] -> [a] -> Bool
> :t allEqual <*> reverse
allEqual <*> reverse :: Eq a => [a] -> Bool
> :t reverse
reverse :: [a] -> [a]
字符串
我试图弄清楚allEqual <*> reverse
中应用程序的示例到底是什么。
我试着解释
f (a -> b) :: [a] -> [a] -> Bool
f a :: [a] -> [a]
f b :: [a] -> Bool
型
但这没有意义,因为f b
与a
相关。
他们是想让ghci告诉我这里实际上使用了什么应用程序f
。如果不是,haskellers是如何推理这些东西的。
2条答案
按热度按时间8wtpewkr1#
你可以使用
-ddump-ds
让GHC显示它正在使用的示例,如下所示:字符串
输出中
<*>
后面的@((->) [a_aSP])
表示它正在使用函数示例(在文档中列为Applicative ((->) r)
示例)。或者,您可以在没有GHC帮助的情况下,仅通过查看类型来解决问题,如下所示:
型
为了简单起见,我将对后两种类型进行alpha转换,以不重用
a
类型变量:型
记住
->
是右相联的,也可以写成前缀形式,所以[t] -> [t] -> Bool
和(->) [t] ([t] -> Bool)
一样。由于allEqual
是<*>
的第一个参数,所以它的类型必须和f (a -> b)
统一。同样,作为第二个参数,reverse
的类型必须和f a
统一,当你把所有的都插进去的时候,你会得到f
必须是(->) [t]
,a
必须是[t]
,并且b
必须是Bool
。快速检查这是否正确是观察f b
然后是[t] -> Bool
,在alpha等价之后是与allEqual <*> reverse
的输出相同的类型GHC推断。由于f
是Applicative
示例所需要的,它必须使用(->) [t]
的示例(以列表为参数的函数)。执行:instances ((->) [t])
将显示instance Applicative ((->) [t]) -- Defined in ‘GHC.Base’
,但实际使用的示例更通用,任何类型的函数都可以使用。一旦找到函数箭头,执行:info (->)
将显示:instance Applicative ((->) r) -- Defined in ‘GHC.Base’
。wko9yo5t2#
我有时使用的一个快速技巧是添加一个类型化的孔,如
(polymorphicValue
asTypeOf_)
。更准确地说,
asTypeOf
是一个定义为字符串
它与
const
非常相似,但它 * 强制 * 它的两个参数x
和y
具有相同的类型。在表达式的中间添加一个类型化的洞
_
,告诉GHC引发一个类型错误,告诉应该使用什么类型来填充这个洞。因此,
(thing
asTypeOf_)
要求GHC打印thing
的类型,这在thing
是多态的时候非常有用。让我们把这个应用到你的案例中:
型
首先,我们将
(<*>)
移动到前缀表示法。型
然后,我们插入键入的孔:
型
我们将了解
(<*>)
的具体示例化类型,即([a] -> [a] -> Bool) -> ([a] -> [a]) -> [a] -> Bool
,以及如何获得该类型的解释。型
显示
<*>
根据(->) [a]
applicative使用,类型为[a]
和Bool
。我们可以描述如下:型