繁体   English   中英

文件夹的派生类型(!!)

[英]Deriving type of foldr (!!)

foldr :: (a->b->b)->b->[a]->b
(!!)::[c]->Int->c

由此我们得到a->b->b=[c]->Int->ca=[c],b=Int,b=c
我们得出结论,文件夹(!!)的类型为Int- Int->[[Int]]->Int
这是正确的吗?
WinGHCi告诉我一些不同:

Prelude> :t foldr (!!)
foldr (!!) :: Foldable t => Int -> t [Int] -> Int

文件foldr :: Foldable t => (a -> b -> b) -> b -> ta -> b实际上在早期确实具有签名(a -> b -> b) -> b -> [a] -> b ,但是他们已经对该函数进行了泛化 ,因此它不仅适用于列表(其中t ~ [] ),而且还适用于其他Foldable类型(例如MaybeSum等)。 但是对于列表情况,没有任何变化,该函数仅适用于更多Foldable类型。

派生“旧”文件foldr的类型

在这种情况下,我们采用以下成分:

foldr :: (a -> b -> b) -> b -> [a] -> b
(!!) :: [c] -> Int -> c

或更详细:

foldr :: (a -> (b -> b)) -> (b -> ([a] -> b))
(!!) :: [c] -> (Int -> c)

由于(!!)是使用foldr作为函数的调用的参数,因此我们知道(!!) :: [c] -> (Int -> c)函数的类型应与的参数类型匹配。 foldr ,所以(a -> b -> b) foldr (a -> b -> b) 因此,这意味着:

  a -> (b -> b)
~ [c] -> (Int -> c)
--------------------
a ~ [c], b ~ c ~ Int

因此我们知道a[c]是同一类型,并且bc实际上都是Int 因此我们知道a ~ [Int]

因此,现在foldr (!!)的类型是foldr的输出类型,但是专门用于我们派生的内容,因此:

b -> ([a] -> b)

等于:

Int -> ([[Int]] -> Int)

或更详细:

Int -> [[Int]] -> Int

推导“ folr的类型

在这种情况下,我们采用以下成分:

foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
(!!) :: [c] -> Int -> c

并且我们对foldr的第一个参数遵循相同的推理:

  a -> (b -> b)
~ [c] -> (Int -> c)
--------------------
a ~ [c], b ~ c ~ Int

因此,文件foldr的输出类型为:

Foldable t => b -> (t a -> b)

或指定我们所知道的:

Foldable t => Int -> t [Int] -> Int

这是ghci派生的。

函数的语义

至于语义,该函数:

f = foldr (!!)

Int (索引)和Int列表的Foldable用作输入。 如果是列表,它将从右到左获取具有该索引的最右边列表的元素,并将该元素用作倒数第二个列表的索引。 我们一直这样做直到第一个列表,然后返回元素。

例如:

foldr (!!) 1 [] -> 1
foldr (!!) 1 [[2, 0]] -> 0
foldr (!!) 1 [[3, 5], [2, 0]] -> 3

对于t ~ Maybe情况,如果为Nothing ,则将返回原始索引,如果为Just [1, 4, 2, 5] Nothing ,则将返回该索引处的元素(一个Just带有一个[Int]对象)。 例如:

foldr (!!) 1 Nothing -> 1
foldr (!!) 3 Nothing -> 3
foldr (!!) 1 (Just [1, 4, 2, 5])-> 4
foldr (!!) 3 (Just [1, 4, 2, 5])-> 5

如评论中所述,在最近的GHC中, foldr :: Foldable t => (a -> b -> b) -> b -> ta -> b Foldable t => Int -> t [Int] -> Int t ~ []Foldable t => Int -> t [Int] -> Int简化为Int->[[Int]]->Int ,如您所愿。

有两种方法可以使GHCi打印更具体的类型。 一种是添加您期望的类型签名,并验证GHCi。

> :t foldr (!!) :: Int->[[Int]]->Int
foldr (!!) :: Int->[[Int]]->Int :: Int -> [[Int]] -> Int

另一种方法是在foldr的普通(项)参数之前给t赋予一个显式类型:

> :t foldr @[] (!!)
foldr @[] (!!) :: Int -> [[Int]] -> Int

这使用TypeApplications 语法为@后跟类型名称。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM