File: WorkerWrapper.hs

package info (click to toggle)
haskell-inspection-testing 0.6.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 208 kB
  • sloc: haskell: 2,053; makefile: 3
file content (35 lines) | stat: -rw-r--r-- 1,617 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{-# LANGUAGE TemplateHaskell #-}
module WorkerWrapper (main) where

import Test.Inspection

-- In this module, we are interested in checking if the worker-wrapper transformation is firing.
-- That transformation is described here:
--    https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/compiler/demand#worker-wrapper-split
-- In short, we don't want to be passing around the dictionary type below, but rather have GHC
-- generate a helper function @$wdictFold :: (m -> m -> m) -> m -> [m] -> m@, as this saves us some
-- wrapping and unwrapping work at each iteration.
--
-- GHC still generates a wrapper at the @dictFold@ name. That is, a function that still consumes the
-- @MonoidDict@ type, but unwraps it just once, before passing it off to @wdictFold@ to handle the
-- recuresion. As @dictFold@ refers to this wrapper, we cannot check that the @MonoidDict@ type is
-- unused in its definition.
--
-- So what are we to do? As the generated wrapper should have an @INLINE@ pragma, once we pass it in
-- the @MonoidDict@, we should be safely in worker-land, and not need to reference @MonoidDict@
-- again. Thus, we look at @appliedFold@, and assert that @MonoidDict@ never shows up -- as would be
-- expected if worker-wrapper fired as hoped.
data MonoidDict a = MonoidDict { dictMappend :: a -> a -> a, dictMempty :: a }

dictFold :: MonoidDict m -> [m] -> m
dictFold bm xs = case xs of
  [] -> dictMempty bm
  x:xs' -> dictMappend bm x $ dictFold bm xs'

appliedFold :: [Int] -> Int
appliedFold = dictFold $ MonoidDict (+) 0

inspect $ 'appliedFold `doesNotUse` 'MonoidDict

main :: IO ()
main = return ()