有关Weak Head Normal Form

参考:https://stackoverflow.com/questions/6872898/haskell-what-is-weak-head-normal-form

Normal form:

An expression in normal form is fully evaluated, and no sub-expression could be evaluated any further (i.e. it contains no un-evaluated thunks).

These expressions are all in normal form:

42
(2, "hello")
\x -> (x + 1)

These expressions are not in normal form:

1 + 2                 -- we could evaluate this to 3
(\x -> x + 1) 2       -- we could apply the function
"he" ++ "llo"         -- we could apply the (++)
(1 + 1, 2 + 2)        -- we could evaluate 1 + 1 and 2 + 2

Weak head normal form

An expression in weak head normal form has been evaluated to the outermost data constructor or lambda abstraction (the head). Sub-expressions may or may not have been evaluated. Therefore, every normal form expression is also in weak head normal form, though the opposite does not hold in general.

WHNF的定义:An expression如果是下面中的一种,则in weak head normal form:

  • a constructor (eventually applied to arguments) like True, Just (square 42) or (:) 1(注意True是Bool的一个Constructor, (:) 1是列表的一个Constructor)
  • a built-in function applied to too few arguments (perhaps none) like (+) 2 or sqrt.
  • or a lambda abstraction \x -> expression.

To determine whether an expression is in weak head normal form, we only have to look at the outermost part of the expression. If it's a data constructor or a lambda, it's in weak head normal form. If it's a function application, it's not.

These expressions are in weak head normal form:

(1 + 1, 2 + 2)       -- the outermost part is the data constructor (,)
 \x -> 2 + 2          -- the outermost part is a lambda abstraction  这只是一个lambda抽象
'h' : ("e" ++ "llo") -- the outermost part is the data constructor (:)

As mentioned, all the normal form expressions listed above are also in weak head normal form.

These expressions are not in weak head normal form:

1 + 2                -- the outermost part here is an application of (+),它是函数应用,不是Constructor
(\x -> x + 1) 2      -- the outermost part is an application of (\x -> x + 1) 这里lambda函数是函数应用,不是一个lambda抽象,注意和上面的区别(当然,如果提供的实参少,则又是WHAT)
"he" ++ "llo"        -- the outermost part is an application of (++)   ++在这里是函数应用

WHNF特点是:参数只计算到第一个 data constructor,它不会把整个值一次全部算出来。
比如 Just (square 42) is WHNF,它不会有进一步的计算
又如 (+) (2 * 3 * 4)也是一个 WHNF,尽管 (2 * 3 * 4)能被简化为标准格式24.

例1

ghci> let t = const (Just "hello") ()
ghci> :sprint t
t =\_
ghci> seq t ()
()
ghci> :sprint t
t = Just _

例2(注意多态)

多态值在被赋予具体的类型前是不会被计算的,即使用seq也不行;

ghci> data F a = SomeVal a 
ghci> let t = SomeVal 3 :: F Int
ghci> :sprint t
t =  3

注意下面是多态,类型不确定

ghci> let t = SomeVal 3
ghci> :sprint t
t = _

两者上面两个例子的区别在于前者类型是确定的
—————————————————————
下面仍然要注意泛型和非泛型的区别

ghci> let t = const (SomeVal 3) ()
ghci> :sprint t
t = \_
ghci> seq t ()
()
ghci> :sprint t
t = _
ghci> 

ghci> let t = const (SomeVal 3) () :: F Int
ghci> :sprint t
t = _
ghci> seq t ()
()
ghci> :sprint t
t =  3

你可能感兴趣的:(有关Weak Head Normal Form)