在Haskell中使用"strict wildcard"什么时候有用,它有什么作用?
When is it useful to use "strict wildcard" in Haskell, and what does it do?
我正在查看一些 Haskell 源代码并遇到与 !_
的模式匹配,代码在这里:http://hackage.haskell.org/package/base-4.9.0.0/docs/src/GHC.List.html#unsafeTake
take n xs | 0 < n = unsafeTake n xs
| otherwise = []
-- A version of take that takes the whole list if it's given an argument less
-- than 1.
{-# NOINLINE [1] unsafeTake #-}
unsafeTake :: Int -> [a] -> [a]
unsafeTake !_ [] = []
unsafeTake 1 (x: _) = [x]
unsafeTake m (x:xs) = x : unsafeTake (m - 1) xs
我不太明白 "strict wildcard" 是如何工作的以及为什么它对这个功能(或任何其他功能)有用。
想法是 unsafeTake
(和 take
就此而言),当被要求 return 空列表的第一个 m
元素时,它应该 return 空列表,无论 m
的值是什么。但是如果 m
是一个抛出异常的表达式呢?例如,unsafeTake undefined []
到 return []
会很奇怪。所以我们需要确保 m
计算为整数,即使我们不关心它的确切值是多少(当然对于空列表的情况)。这使得 unsafeTake
在涉及第一个参数时表现相同,而不管第二个参数(列表)是否为空。
我正在查看一些 Haskell 源代码并遇到与 !_
的模式匹配,代码在这里:http://hackage.haskell.org/package/base-4.9.0.0/docs/src/GHC.List.html#unsafeTake
take n xs | 0 < n = unsafeTake n xs
| otherwise = []
-- A version of take that takes the whole list if it's given an argument less
-- than 1.
{-# NOINLINE [1] unsafeTake #-}
unsafeTake :: Int -> [a] -> [a]
unsafeTake !_ [] = []
unsafeTake 1 (x: _) = [x]
unsafeTake m (x:xs) = x : unsafeTake (m - 1) xs
我不太明白 "strict wildcard" 是如何工作的以及为什么它对这个功能(或任何其他功能)有用。
想法是 unsafeTake
(和 take
就此而言),当被要求 return 空列表的第一个 m
元素时,它应该 return 空列表,无论 m
的值是什么。但是如果 m
是一个抛出异常的表达式呢?例如,unsafeTake undefined []
到 return []
会很奇怪。所以我们需要确保 m
计算为整数,即使我们不关心它的确切值是多少(当然对于空列表的情况)。这使得 unsafeTake
在涉及第一个参数时表现相同,而不管第二个参数(列表)是否为空。