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

时间:2018-07-25 11:47:07

标签: haskell types ghci unification

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

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

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

2 个答案:

答案 0 :(得分:6)

早期的foldr :: Foldable t => (a -> b -> b) -> b -> t a -> 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)函数的类型应与{{1}的参数类型匹配},因此foldr。这意味着:

(a -> b -> b)

因此,我们知道 a -> (b -> b) ~ [c] -> (Int -> c) -------------------- a ~ [c], b ~ c ~ Int a的类型相同,并且[c]b实际上都是c。因此,我们知道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个列表中的Foldable作为输入。如果是列表,它将从右到左获取具有该索引的最右边列表的元素,并将该元素用作倒数第二个列表的索引。我们一直这样做直到第一个列表,然后返回元素。

例如:

Int

对于foldr (!!) 1 [] -> 1 foldr (!!) 1 [[2, 0]] -> 0 foldr (!!) 1 [[3, 5], [2, 0]] -> 3 情况,如果是t ~ Maybe,我们将返回原始索引;如果是Nothing,我们将返回该索引处的元素(a带有Just [1, 4, 2, 5]对象的Just。例如:

[Int]

答案 1 :(得分:4)

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

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

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

另一种方法是在t的常规(项)参数之前给foldr提供一个显式类型:

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

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