{-# NOINLINE [1] unsafeTake #-}
unsafeTake :: Int -> [a] -> [a]
unsafeTake !_ [] = []
unsafeTake 1 (x: _) = [x]
unsafeTake m (x:xs) = x : unsafeTake (m - 1) xs
我的理解是!
删除了thunk。好的,但_
被忽略了。有些东西我不理解。澄清表示赞赏。
答案 0 :(得分:4)
那是BangPattern。它是一个注释告诉编译器,该函数在其第一个参数中应该表现得严格。它等同于以下代码:
unsafeTake :: Int -> [a] -> [a]
unsafeTake x [] = x `seq` []
unsafeTake 1 (x: _) = [x]
unsafeTake m (x:xs) = m `seq` (x : unsafeTake (m - 1) xs)
该字段是严格的,意味着如果第一个参数恰好是底部,则程序停止:
unsafeTake (error "kaboom") []
这将使kaboom具有严格的注释,但如果它没有它,它将不会发生。
您还可以将Bang Patterns放入数据类型定义中:
data Tree a = Branch (Tree a) !a (Tree a)
| Empty
然后它将始终将包含 a 的字段评估为其弱头正常形式。这意味着它不会评估整个结构。来自haskell wiki
答案 1 :(得分:1)
它告诉编译器即使第二个参数是[]
,然后它知道它可以应用第一个替代,它仍然应该评估第一个参数为head normal form。这意味着unsafeTake
在其第一个参数中是'严格'。
如果您尝试评估unsafeTake (last (repeat 0)) []
与take
相比,则可以看到结果。