这两者之间的区别很微妙。那里
是
这个
Value
类型
Value
以及它的内部表示。这立即意味着
Bool
(当然,
Null
必须
每年进行一次全面评估
价值
根据WHNF进行评估。
接下来,让我们考虑一下
String
和
Number
这个
严格的
Text
所以那里也不会有懒惰。类似地
数字
Scientific
值,内部由两个严格值表示。二者都
一串
数字
而且
每年进行一次全面评估
根据WHNF进行评估。
我们现在可以把注意力转向
Object
和
Array
对象
在aeson中,s由a表示
懒惰的
HashMap
懒惰的
大堆
s是
Vector
价值
s可以包含thunk。
考虑到这一点,我们知道,一旦我们有了
价值
只有
放置
decode
和
decode'
不同之处在于对象和数组的生成。
接下来,我们可以尝试实际评估GHCi中的一些内容,看看会发生什么。我们从一系列导入和定义开始:
:seti -XOverloadedStrings
import Control.Exception
import Control.Monad
import Data.Aeson
import Data.ByteString.Lazy (ByteString)
import Data.List (foldl')
import qualified Data.HashMap.Lazy as M
import qualified Data.Vector as V
:{
forceSpine :: [a] -> IO ()
forceSpine = evaluate . foldl' const ()
:}
let jsonDocument = "{ \"value\": [1, { \"value\": [2, 3] }] }" :: ByteString
let !parsed = decode jsonDocument :: Maybe Value
let !parsed' = decode' jsonDocument :: Maybe Value
force parsed
force parsed'
现在我们有两个绑定,
parsed
和
parsed'
,其中一个用
解码
。他们被强迫使用WHNF,这样我们至少可以看到他们是什么,但我们可以使用
:sprint
ghci> :sprint parsed
parsed = Just _
ghci> :sprint parsed'
parsed' = Just
(Object
(unordered-containers-0.2.8.0:Data.HashMap.Base.Leaf
15939318180211476069 (Data.Text.Internal.Text _ 0 5)
(Array (Data.Vector.Vector 0 2 _))))
仍然未评估,但使用
解码'
有一些数据。这让我们看到了两者之间第一个有意义的区别:
将其直接结果强制给WHNF,但是
将其推迟到需要时。
让我们看看这些值,看看我们是否能找到更多的差异。一旦我们评估这些外部物体,会发生什么?
let (Just outerObjValue) = parsed
let (Just outerObjValue') = parsed'
force outerObjValue
force outerObjValue'
ghci> :sprint outerObjValue
outerObjValue = Object
(unordered-containers-0.2.8.0:Data.HashMap.Base.Leaf
15939318180211476069 (Data.Text.Internal.Text _ 0 5)
(Array (Data.Vector.Vector 0 2 _)))
ghci> :sprint outerObjValue'
outerObjValue' = Object
(unordered-containers-0.2.8.0:Data.HashMap.Base.Leaf
15939318180211476069 (Data.Text.Internal.Text _ 0 5)
(Array (Data.Vector.Vector 0 2 _)))
这很明显。我们显式地强制这两个对象,因此现在它们都被计算为哈希映射。真正的问题是他们的
元素
进行评估。
let (Array outerArr) = outerObj M.! "value"
let (Array outerArr') = outerObj' M.! "value"
let outerArrLst = V.toList outerArr
let outerArrLst' = V.toList outerArr'
forceSpine outerArrLst
forceSpine outerArrLst'
ghci> :sprint outerArrLst
outerArrLst = [_,_]
ghci> :sprint outerArrLst'
outerArrLst' = [Number (Data.Scientific.Scientific 1 0),
Object
(unordered-containers-0.2.8.0:Data.HashMap.Base.Leaf
15939318180211476069 (Data.Text.Internal.Text _ 0 5)
(Array (Data.Vector.Vector 0 2 _)))]
解码
,值不是强制的,而是用
是正如你所见,这意味着
解码
在实际需要Haskell值之前,不会对其进行转换,这就是文档所说的延迟转换的意思。
影响
显然,这两个功能是
轻微地
不同,而且很明显,
解码'
比严格
解码
嗯,值得一提的是
解码
解码'
解码
可能是正确的默认值。当然
永远不会比
解码
避免分配
当然,懒惰也不是免费的。懒惰意味着添加thunk,这可能需要花费空间和时间。无论如何,如果要评估所有Thunk,那么
解码
从这个意义上讲,您可能希望使用
解码'
在这种情况下
无论如何,结构将被强迫,这可能取决于
FromJSON
您正在使用的实例。一般来说,除非性能真的很重要,否则我不会担心在它们之间进行选择
和
和
解码'