我不确定我是否理解haskell中foldl函数的类型定义
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我不确定我是否理解haskell中foldl函数的类型定义相关的知识,希望对你有一定的参考价值。
当我问到foldl类型时,我看到的是:
*Main> :t foldl
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
在这种情况下,什么是t a
?
我想这意味着该函数使用Foldable
参数化a
,但我甚至不确定语法。例如,为什么我不能用t a
替换Foldable a
?
而且,奖金问题,如果我必须自己定义foldl
,我会从基础案例开始
foldl f b [] = []
但是如果基本案例采用列表,那么接受Foldable
就没有多大意义了。什么是我可以用作基本案例的“空可折叠”?
Foldable
被称为“类型类”。说Foldable t =>
声明t
必须实现Foldable
的要求。然而,t
仍然是t
,并没有像Java中那样折叠成对Foldable
接口的引用。这就是为什么你不能只有Foldable a
。
绝对查看https://hackage.haskell.org/package/base-4.10.1.0/docs/Data-Foldable.html以了解Foldable
的要求以及可以获得哪些方法。
无论如何,如果你想使用Foldable
的方法之一,那么要么使用像Foldable
这样的已知Set
类型:
import qualified Data.Set as S
import Data.Foldable
sumSet :: (Num n) => S.Set n -> n
sumSet ns = foldl' ( n acc -> n + acc ) 0 ns --make this pointfree if you want
或者您可以采用类型参数并将其约束为可折叠:
sumFld :: (Num n, Foldable f) => f n -> n --different signature
sumFld ns = foldl' ( n acc -> n + acc ) 0 ns --same implementation!
以下打印6,两次:
main :: IO ()
main = print (sumSet $ S.fromList [1, 2, 3]) >> print (sumFld $ S.fromList [1, 2, 3])
我喜欢其他答案,这些答案简要讨论了类型和类之间的区别,因此以这种方式回答问题的前半部分。为了完成这个答案,我将非常简短地重申一下;但是请看其他答案以获得更长的解释,因为我想把大部分时间花在问题的后半部分。
所以:Foldable
是类型类(类型集合)。 t
类型的foldl
游侠类型,而不是类型的集合,这解释了为什么它不能被Foldable
取代。
但我认为这也是一个非常有趣的问题,其他答案没有解决:
如果我必须自己定义
foldl
,我将从基础案例开始foldl f b [] = []
但是如果基本案例采用列表,那么接受
Foldable
就没有多大意义了。
如果你自己定义foldl
,你将为特定类型创建一个Foldable
实例。因为在实例中您知道涉及哪种特定类型,所以您可以为该类型编写基本案例,而无需了解Foldable
的任何其他实例。在列表的Foldable
实例中:
instance Foldable [] where
foldl f b [] = b
...是完美的打字,因为我们知道t ~ []
。另一方面,在另一种类型的实例中,我们当然必须使用不同的基本情况。例如:
import qualified Data.Set as S
instance Foldable S.Set where
foldl f b s | S.null s = b
再次,这在instance
区块内是可以的,因为那时我们有t ~ S.Set
。我们可以(并且通常必须)编写仅适用于S.Set
s的内容,并且不能与其他Foldable
实例一起使用。
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
在这种情况下,什么是
t a
?我想这意味着该函数正在使用
Foldable
参数化a
[...]
这是完全正确的。但请注意,它是“用Foldable
参数化的a
”,而不是“用Foldable
参数化的a
”。正如hegel5000's answer解释的那样,当你在Foldable t
的左边写=>
时,你说的是类型(构造函数)t
。用t a
替换Foldable a
有点像将名词放在名词应该是的位置。
继续你的奖金问题:foldl
碰巧是Foldable
类的方法。这意味着当你为一个类型编写一个Foldable
实例时,你能够提供一个合适的foldl
定义,你可以在其中使用该类型的特定特征(例如,[]
是列表的构造函数 - 参见Daniel Wagner's answer)。
但是,如果foldl
不是Foldable
的方法,那么在实现它时你能用来处理t a
论证的唯一方法就是Foldable
(foldr
,foldMap
等)的(其他)方法,就像你一样除了它有一个t
实例的事实之外,我不知道关于Foldable
的任何其他事情。 (也许令人惊讶的是,有可能以这种方式实现foldl
。这样的实现是作为foldl
类中的Foldable
方法的默认实现提供的,因此如果你不做,那么在编写实例时你不必自己实现它。不认为有必要。)
在(Foldable t) => ...
的背景下,t
是可折叠的类型。这方面的一个例子可能是列表类型[]
。
foldl
的一些更具体的类型将是
foldl :: (b -> a -> b) -> b -> [a] -> b
foldl :: (b -> a -> b) -> b -> Tree a -> b
Foldable t => ...
可以理解为t
必须是Foldable
。它不是应用于Foldable
类型的类型构造函数t
!因此Foldable t
甚至不是一种类型,你不能在=>
的右侧使用它。
以上是关于我不确定我是否理解haskell中foldl函数的类型定义的主要内容,如果未能解决你的问题,请参考以下文章