组合 "length of sum" 是什么意思?
What does the composition "length of sum" mean?
我在玩 Haskell 中的类型,无意中发现 length . sum
是有效的。是否有一些语义应该允许它工作,或者这仅仅是类型定义的一个缺点?我在下面写了每个类型定义。
length :: Foldable t => t a -> Int
sum :: (Foldable t, Num a) => t a -> a
(.) :: (b -> c) -> (a -> b) -> a -> c
length . sum :: (Foldable t1, Foldable t2, Num (t1 a)) => t2 (t1 a) -> Int
我唯一能理解的场景是将字符求和成一个字符串,然后您就可以得到该字符串的长度。但是,sum 只能接受可折叠类型的数字,因此无法工作。
这是一个简单的例子。
import Data.Functor.Identity
xs :: [Identity Int]
xs = map Identity [0..9]
result :: Int
result = length . sum $ xs
main :: IO ()
main = print result -- 1
让我们了解发生了什么。
- 首先,我们对
xs
的所有元素求和。因此,sum xs
是 Identity 0 + ... + Identity 9
,计算结果为 Identity 45
。请注意 Num a => Identity a
是 Num
. 的一个实例
- 接下来,我们求
sum xs
的长度。因此,length . sum $ xs
是 length $ Identity 45
,其计算结果为 1
,因为在任何 Identity
数据结构中只有一个元素。
如果您查看 length . sum
的签名,这是有道理的。
length . sum :: (Foldable g, Foldable f, Num (f a)) => g (f a) -> Int
首先,我们遍历g
,找到g
内所有f a
的sum
。 sum
的定义取决于类型 f a
。结果是 f a
。然后,我们找到结果 f a
.
的 length
我在玩 Haskell 中的类型,无意中发现 length . sum
是有效的。是否有一些语义应该允许它工作,或者这仅仅是类型定义的一个缺点?我在下面写了每个类型定义。
length :: Foldable t => t a -> Int
sum :: (Foldable t, Num a) => t a -> a
(.) :: (b -> c) -> (a -> b) -> a -> c
length . sum :: (Foldable t1, Foldable t2, Num (t1 a)) => t2 (t1 a) -> Int
我唯一能理解的场景是将字符求和成一个字符串,然后您就可以得到该字符串的长度。但是,sum 只能接受可折叠类型的数字,因此无法工作。
这是一个简单的例子。
import Data.Functor.Identity
xs :: [Identity Int]
xs = map Identity [0..9]
result :: Int
result = length . sum $ xs
main :: IO ()
main = print result -- 1
让我们了解发生了什么。
- 首先,我们对
xs
的所有元素求和。因此,sum xs
是Identity 0 + ... + Identity 9
,计算结果为Identity 45
。请注意Num a => Identity a
是Num
. 的一个实例
- 接下来,我们求
sum xs
的长度。因此,length . sum $ xs
是length $ Identity 45
,其计算结果为1
,因为在任何Identity
数据结构中只有一个元素。
如果您查看 length . sum
的签名,这是有道理的。
length . sum :: (Foldable g, Foldable f, Num (f a)) => g (f a) -> Int
首先,我们遍历g
,找到g
内所有f a
的sum
。 sum
的定义取决于类型 f a
。结果是 f a
。然后,我们找到结果 f a
.
length