Guest User

Untitled

a guest
Jan 22nd, 2018
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.90 KB | None | 0 0
  1. > {-# LANGUAGE MagicHash #-}
  2. > module WorkerWrapper where
  3. > import Prelude hiding (replicate, abs)
  4. > import GHC.Prim (Int#)
  5. > import GHC.Exts (Int(I#), (==#), (-#), (*#))
  6. > import Data.Function (fix)
  7.  
  8. > fac :: Int -> Int
  9. > fac 0 = 1
  10. > fac n = n * fac (n - 1)
  11.  
  12. このfacはunboxingとboxingで非効率。nに対して正格なので、Int#に置き換えても良い。
  13. まずはfacを最小不動点で書き直す。これはInt -> Intな関数をInt# -> Int#に書き直す
  14. ことが目的である。
  15.  
  16. > fac1 :: Int -> Int
  17. > fac1 = fix body
  18. >
  19. > body :: (Int -> Int) -> (Int -> Int)
  20. > body f 0 = 1
  21. > body f n = n * f (n - 1)
  22.  
  23. 次に変換関数を書く。
  24.  
  25. > rep :: Int -> Int#
  26. > rep x = case x of
  27. > I# y# -> y#
  28. >
  29. > abs :: Int# -> Int
  30. > abs y# = I# y#
  31.  
  32. > unwrap :: (Int -> Int) -> Int# -> Int#
  33. > unwrap f y# = rep (f (abs y#))
  34. >
  35. > wrap :: (Int# -> Int#) -> Int -> Int
  36. > wrap g# x = abs (g# (rep x))
  37.  
  38. f :: Int -> Intが正格なら、
  39. wrap . unwrap = id
  40. を満たす。body1は引数nに対して正格なので、
  41. wrap . unwrap . body1 = body1
  42. がいえる。
  43.  
  44. これをfac1に適用する。
  45.  
  46. fix body1
  47. = { idを差し込む }
  48. fix (id . body1)
  49. = { wrap . unwrap = id }
  50. fix (wrap . unwrap . body1)
  51. = { rolling rule }
  52. wrap (fix (unwrap . body1 . wrap))
  53. = { fix (unwrap . body . wrap)をwork2と定義する
  54. wrap work2
  55.  
  56. > fac2 :: Int -> Int
  57. > fac2 = wrap work2
  58. >
  59. > work2 :: Int# -> Int#
  60. > work2 = unwrap (body (wrap work2))
  61.  
  62. 続いてfac2のwrapを展開する。
  63.  
  64. > fac' :: Int -> Int
  65. > fac' n = case n of
  66. > I# y# -> I# (work' y#)
  67.  
  68. worker関数も展開する。
  69.  
  70. work
  71. => { workの定義 }
  72. unwrap (body (wrap work)) n#
  73. => { unwrapを展開 }
  74. rep (body (wrap work) (abs n#))
  75. => { bodyを展開 }
  76. rep (case abs n# of
  77. 0 -> 1
  78. n -> n * (wrap work) (n - 1))
  79. => { repをcaseで分配 }
  80. case abs n# of
  81. 0 -> rep 1
  82. n -> rep (n * (wrap work) (n - 1))
  83. => { 最適化してabs/repの除去 }
  84. case n# of
  85. 0# -> 1#
  86. n# -> n# *# work (n# -# 1#)
  87.  
  88. > work' :: Int# -> Int#
  89. > work' 0# = 1#
  90. > work' n# = n# *# work' (n# -# 1#)
  91.  
  92.  
  93. replicateの場合も考える。
  94.  
  95. > replicate :: Int -> a -> [a]
  96. > replicate 0 _ = []
  97. > replicate n x = x : replicate (n - 1) x
  98.  
  99. まずは最小不動点で書き直す。
  100.  
  101. > replicate1 :: Int -> a -> [a]
  102. > replicate1 = fix body'
  103. >
  104. > body' :: (Int -> a -> [a]) -> Int -> a -> [a]
  105. > body' _ 0 _ = []
  106. > body' f n x = x : f (n - 1) x
  107.  
  108. wrap/unwrapを定義する。
  109.  
  110. > unwrap' :: (Int -> a -> [a]) -> Int# -> a -> [a]
  111. > unwrap' f n# = f (abs n#)
  112. >
  113. > wrap' :: (Int# -> a -> [a]) -> Int -> a -> [a]
  114. > wrap' f n = f (rep n)
  115.  
  116. workerとwrapperに分割する。
  117.  
  118. > replicate2 :: Int -> a -> [a]
  119. > replicate2 = wrap' work'2
  120. >
  121. > work'2 :: Int# -> a -> [a]
  122. > work'2 = unwrap' (body' (wrap' work'2))
  123.  
  124. 展開しておしまい。
  125.  
  126. > replicate' :: Int -> a -> [a]
  127. > replicate' n x = case n of
  128. > I# n# -> work'' n# x
  129. >
  130. > work'' :: Int# -> a -> [a]
  131. > work'' n# x = case n# of
  132. > 0# -> []
  133. > n# -> x : work'' (n# -# 1#) x
Add Comment
Please, Sign In to add comment