$ cabal install lens
$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
> import Control.Lens
访问列表
使用中缀运算符访问列表
> [1,2,3,4,5] ^? element 2 -- 0 based indexing
Just 3
Unlike the (!!) this will not throw an exception when accessing an element out of bounds and will return Nothing instead. It is often recommend to avoid partial functions like (!!) or head since they have more corner cases and are more likely to cause a run time error. You can read a little more about why to avoid partial functions at 这个维基页面.
> [1,2,3] !! 9
*** Exception: Prelude.(!!): index too large
> [1,2,3] ^? element 9
Nothing
We can now access the elements of the tree in depth-first order:
> tree ^? element 0
Just 1
> tree ^? element 1
Just 2
> tree ^? element 2
Just 4
> tree ^? element 3
Just 5
> tree ^? element 4
Just 3
> tree ^? element 5
Just 6
> tree ^? element 6
Just 7
Digging down into nested structures is simple with the lens 黑客攻击. For example accessing an element in a list of lists:
> [[1,2,3],[4,5,6]] ^? element 0 . element 1
Just 2
> [[1,2,3],[4,5,6]] ^? element 1 . element 2
Just 6
即使嵌套数据结构的类型不同,此组合也能正常工作。例如,如果我有一个树的列表:
> :{
let
tree = Node 1 [
Node 2 []
, Node 3 []
]
:}
> putStrLn . drawTree . fmap show $ tree
1
|
+- 2
|
`- 3
> :{
let
listOfTrees = [ tree
, fmap (*2) tree -- All tree elements times 2
, fmap (*3) tree -- All tree elements times 3
]
:}
> listOfTrees ^? element 1 . element 0
Just 2
> listOfTrees ^? element 1 . element 1
Just 4
atDefault :: a -> Integer -> [a] -> a
atDefault aDef _ [] = aDef -- case: is empty anyway
atDefault _ 0 (a:_) = a -- case: index is 0 -> take it
atDefault aDef nIndex (a:la)
| nIndex > 0 = atDefault aDef (nIndex - 1) la -- case: index is positive
| otherwise = aDef -- case: index is negative
A use case might be the following:
您希望通过使用八进制字节列表实现一组无穷尽的数字。假设列表总是有一组给定的 n 个元素,假设 n 是 > 0-但是元素也可能被访问,这时你通常认为它超出了索引范围(index > = n 或 index < 0)-但是你没有访问。相反,您将提供0作为默认值。
例如:
module Main where
import qualified Data.Word as W
import qualified Data.Bits as Bts
import Data.Bits ((.|.))
import qualified Data.List as L
main :: IO ()
main = do
print $ atDefault 0x00 (-1) myOctet
print $ atDefault 0x00 0 myOctet
print $ atDefault 0x00 1 myOctet
print $ atDefault 0x00 2 myOctet
print $ atDefault 0x00 3 myOctet
print $ atDefault 0x00 4 myOctet
myOctet = toOctets (0xA4B3C2D1 :: W.Word32)
atDefault :: a -> Integer -> [a] -> a
atDefault aDef _ [] = aDef -- case: is empty anyway
atDefault _ 0 (a:_) = a -- case: index is 0 -> take it
atDefault aDef nIndex (a:la)
| nIndex > 0 = atDefault aDef (nIndex - 1) la -- case: index is positive
| otherwise = aDef -- case: index is negative
class Octetable w where
toOctets :: w -> [W.Word8]
instance Octetable W.Word32 where
toOctets w32 =
[ fromIntegral (w32 `Bts.shiftR` 24)
, fromIntegral (w32 `Bts.shiftR` 16)
, fromIntegral (w32 `Bts.shiftR` 8)
, fromIntegral w32
]