Understanding Grading Order in Haskell

I am trying to understand how offers are evaluated in Haskell. Let's say we have this toy example where the bar, base and bat are defined somewhere:

func x = foo i j k
  where
    foo i j k = i + j + k
    k = bat x
    j = baz k
    i = bar j

How does the string expand func x = foo i j k? Does this mean something like func x = foo(i(j(k)), j(k), k)or func x = foo(i, j, k)?

+4
source share
4 answers

Introduction

I assume you wanted to write this code:

func :: Int -> Int
func x = foo
  where
    foo = i + j + k
    k = bat x
    j = baz k
    i = bar j

, , , where, . , , , , , . , , .

Core

, , GHC, , , .

-, "where clauses" "let clauses". , Haskell Core. , -, . :

func = λx ->
      let { k = bat x } in
      let { j = baz k } in
      +
        (+ (bar j) j)
        k

, where Haskell (, ), let . (+) , ( , i + j). .

- Spineless Tagless Graph. , Core to STG - , , , - . ( , .) STG , , , , - , Core ( 4) , , Core .

Core . , Haskell - . , : . (, ), , , . , , , .

, Core , . :

enter image description here

, , , . :

  • x, , func func x.

  • . , , .

, STG , , , .

, , , :

  • func x .
  • bat x .
  • k , bat x. ( , , , GHC , let , .)
  • baz k .
  • j , baz k, , k 6. bar j .
  • , 3 5, i . Core , .
  • + (bar j) j. j , baz k , .
  • . , bat x , .
  • func x , .

, , , .

, . : Haskell Graph Machine, GHC .

Core, GHC, -ddump-simpl . , .

!

@ , , , . : , , . , , . : f x = 3. : , x , " " , x, , . , , , . , , .

+8

( Haskell) . Num.

, Num . Show , .

import Debug.Trace

newtype LeftFirst = LF { unLF :: Integer }
instance Show LeftFirst where show (LF x) = x `seq` "LF"++show x
newtype RightFirst = RF { unRF :: Integer }
instance Show RightFirst where show (RF x) = x `seq` "RF"++show x

instance Num LeftFirst where
    (+) a b = a `seq` LF (unLF a + unLF b)
    fromInteger x = trace ("LF" ++ show x) (LF x)

instance Num RightFirst where
    (+) a b = b `seq` RF (unRF a + unRF b)
    fromInteger x = trace ("RF" ++ show x) (RF x)

func :: Num a => a -> a
func x = foo i j k
  where
    foo i j k = i + j + k
    k = bat x
    j = baz k
    i = bar j

bar,baz,bat :: Num a => a -> a
bar = (+1)
baz = (+2)
bat = (+3)

:

*Main> func (0 :: LeftFirst)
LF0
LF3
LF2
LF1
LF14
*Main> func (0 :: RightFirst)
RF3
RF0
RF2
RF1
RF14
+5

foo i j k ((foo i) j) k. , Haskell . foo i, (foo i) , arg j .. , foo(i(j(k))) foo (i, j, k); , ((foo i) j) k , foo (i, j, k) , , .

-, i, j k foo , , foo, ( foo), . (+), , . , i, , , i, , , x.

, , "" " ". i -, , - i - i, , i .

+3

( ), , " " , Haskell . , (.. "" ):

func x = foo i j k
  where
    foo i j k = i + j + k
    k = bat x
    j = baz k
    i = bar j

, , func 10. ?

, :

  • (, , x k x func x ..)
  • " ", Haskell, , .

, where, , where "" - where func x. where :

-, , ( func) ( x). func x where func x func x, ( , where func x , "" - ). , x k = bat x x func x.

-, , where ( foo, k, j i), , i, j k foo i j k NOT , -Wall . - :

func x = foo i j k
  where
    foo i' j' k' = i' + j' + k'
    k = bat x
    j = baz k
    i = bar j

. , k in j = baz k k, k = bat x, j in i = bar j j, j = baz k, i, j k, where, i', j' k' foo i' j' k'. , . :

func x = foo i j k
  where
    foo i' j' k' = i' + j' + k'
    i = bar j
    j = baz k
    k = bat x

. , i = bar j j, - j.

-, where , . func x = foo i j k foo, k, j i. ( , , - - where func x, , , -Wall , .)

, :

func x = foo i j k
  where
    foo i' j' k' = i' + j' + k'
    k = bat x
    j = baz k
    i = bar j

(, k ).

Now the link transparency rule comes into effect. You can determine the meaning of an expression by replacing any name by its definition (trying to avoid name collisions or the so-called “capture” of names). Therefore, if we were to evaluate func 10, it would be tantamount to:

func 10                                        -- binds x to 10
= foo i j k                                    -- by defn of func

at this stage, a definition is used foothat associates i'with i, j'with jand k'to k, to obtain the expression:

= i + j + k                                    -- by defn of foo
= bar j + baz k + bat x                        -- by defs of i, j, k
= bar (baz k) + baz k + bat x                  -- by defn of j
= bar (baz (bat x)) + baz (bat x) + bat x      -- by defn of k
= bar (baz (bat 10)) + baz (bat 10) + bat 10   -- by defn of x

So, if we determined:

bat = negate
baz y = 7 + y
bar z = 2*z

then we expect:

func 10 = 2 * (7 + negate 10) + (7 + negate 10) + negate 10
        = -19

what we get:

> func 10
-19
+2
source

Source: https://habr.com/ru/post/1692539/


All Articles