git.iko.soy/typeable/haskell-stack-trace-plugin
on 0f358f0 help sign in
10 files changed+88−202
since splitsnapshots
unifiedsplit
.github/workflows/cabal.yml+28−16 .gitignore+1−2 CHANGELOG.md−16 LICENSE+1−1 Readme.md+22−30 example/Main.hs+3−9 haskell-stack-trace-plugin.cabal+16−14 src/StackTrace/Plugin.hs+14−109 test/StackTrace/PluginSpec.hs+1−1 test/resource/ghc.output → test/resource/ghc86.output+2−4
.github/workflows/cabal.yml+28−16
@@ -2,9 +2,13 @@ name: cabal
22
33on:
44 push:
5− branches: [ master ]
5+ branches:
6+ - master
7+ tags-ignore:
8+ - '*'
69 pull_request:
7− branches: [ '*' ]
10+ branches:
11+ - '*'
812 schedule:
913 - cron: "00 15 * * *"
1014
@@ -13,32 +17,40 @@ jobs:
1317 runs-on: ubuntu-18.04
1418 strategy:
1519 matrix:
16− ghc: ["8.6", "8.8", "8.10", "9.0"]
17− cabal: ["3.2"]
18− cache-version: ["2021-05-21"]
20+ ghc: ["8.6.5"]
21+ cabal: ["3.0"]
1922
2023 steps:
2124 - uses: actions/checkout@v2
22− - uses: haskell/actions/setup@v1
25+ - uses: actions/setup-haskell@v1
2326 with:
2427 ghc-version: ${{ matrix.ghc }}
2528 cabal-version: ${{ matrix.cabal }}
2629
30+ - name: Display ghc & cabal version
31+ run: |
32+ ghc -V
33+ cabal -V
34+
2735 - name: Cache ~/.cabal/store
28− uses: actions/cache@v2
36+ uses: actions/cache@v1.1.0
37+ with:
38+ path: ~/.cabal/store
39+ key: ${{ matrix.ghc }}-v0-cabal-store-${{ hashFiles('*.cabal') }}
40+
41+ - name: Cache dist-newstyle
42+ uses: actions/cache@v1.1.0
2943 with:
30− path: |
31− ~/.cabal/store
32− dist-newstyle
33− key: ${{ runner.os }}-${{ matrix.ghc }}-${{ matrix.cache-version }}-cabal
44+ path: dist-newstyle
45+ key: ${{ matrix.ghc }}-v0-cabal-dist-${{ hashFiles('*.cabal') }}
3446
3547 - name: Install dependencies
3648 run: |
37− cabal update
38− cabal configure --disable-optimization --enable-tests --write-ghc-environment-files=always -j2
39− cabal build --only-dependencies
49+ cabal v2-update
50+ cabal v2-configure --disable-optimization --enable-tests --write-ghc-environment-files=always -j2
51+ cabal v2-build --only-dependencies
4052
4153 - name: Build & Test
4254 run: |
43− cabal build --flag dev
44− cabal test --flag dev
55+ cabal v2-build --flag dev
56+ cabal v2-test --flag dev
.gitignore+1−2
@@ -3,5 +3,4 @@ dist-*/
33.ghc.environment.*
44cabal.project.local
55
6−*~
7−tasks.json
6+*~
CHANGELOG.md−16
@@ -1,21 +1,5 @@
11# Revision history for haskell-stack-trace-pugin
22
3−## Unreleased changes
4−
5−## 0.1.3.0
6−
7−- Added support `where` clause [#11](https://github.com/waddlaw/haskell-stack-trace-plugin/pull/11) (@waddlaw)
8−- Avoid redundant-constraints warnings [#12](https://github.com/waddlaw/haskell-stack-trace-plugin/pull/12) (@waddlaw)
9−
10−## 0.1.2.0 -- 2021-05-21
11−
12−- Added support for GHC 8.10 [#7](https://github.com/waddlaw/haskell-stack-trace-plugin/pull/7) (@etorreborre)
13−- Added support for GHC 9.0 @waddlaw
14−
15−## 0.1.1.1 -- 2020-01-18
16−
17−- Allow GHC-8.8.1
18−
193## 0.1.1.0 -- 2020-01-18
204
215- Ergonomic improvements [#1](https://github.com/waddlaw/haskell-stack-trace-plugin/pull/1) (@khwarizmii)
LICENSE+1−1
@@ -1,4 +1,4 @@
1−Copyright (c) 2018-2021 Shinya Yamaguchi
1+Copyright (c) 2018-2020 Shinya Yamaguchi
22
33Permission is hereby granted, free of charge, to any person obtaining
44a copy of this software and associated documentation files (the
Readme.md+22−30
@@ -5,10 +5,8 @@
55
66This plugin allow implicitly add `HasCallStack` class to every top-level function for all module. Hence, we can to get completely continuous call stack.
77
8−1. (implicitly) Import [GHC.Stack](https://hackage.haskell.org/package/base/docs/GHC-Stack.html) for all modules.
9−2. Add [HasCallStack](https://hackage.haskell.org/package/base/docs/GHC-Stack.html#t:HasCallStack) constraint for all top-level functions.
10−3. Other supported syntaxes
11− - [x] `where` clause
8+1. (implicitly) Import [GHC.Stack](https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-Stack.html) for all modules.
9+2. Add [HasCallStack](https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-Stack.html#t:HasCallStack) constraint for all top-level functions.
1210
1311Requirement: (8.6 <= on GHC)
1412
@@ -34,10 +32,10 @@ f3 = f4 0
3432
3533-- HsQualTy
3634f4 :: Show a => a -> Int
37−f4 n = f5 (show n) 0
35+f4 _ = f5 0 0
3836
3937-- HsFunTy
40−f5 :: String -> Int -> Int
38+f5 :: Int -> Int -> Int
4139f5 _ _ = head f6
4240
4341-- HsListTy
@@ -50,13 +48,7 @@ f7 = (fromJust f8, fromJust f8)
5048
5149-- HsAppTy
5250f8 :: Maybe Int
53−f8 = Just f9
54−
55−f9 :: Int
56−f9 = f10
57− where
58− f10 :: Int
59− f10 = fError
51+f8 = Just fError
6052
6153-- HsTyVar
6254fError :: Int
@@ -66,7 +58,7 @@ fError = error "fError"
6658This example get error:
6759
6860```shell
69−$ cabal build
61+$ cabal new-build
7062example/Main.hs:15:7: error:
7163 Not in scope: type constructor or class ‘HasCallStack’
7264 |
@@ -79,10 +71,10 @@ Yes, add `import GHC.Stack` to above example.
7971Fix and rebuild!
8072
8173```shell
82−$ cabal run example -v0
74+$ cabal new-run
8375example: fError
8476CallStack (from HasCallStack):
85− error, called at example/Main.hs:47:10 in main:Main
77+ error, called at example/Main.hs:41:10 in main:Main
8678```
8779
8880Hmm, it is not useful. But, you will to be happy when enable this plugin.
@@ -93,22 +85,22 @@ Hmm, it is not useful. But, you will to be happy when enable this plugin.
9385```
9486
9587```shell
96−$ cabal run example -v0
88+$ cabal new-run
89+...
90+
9791example: fError
9892CallStack (from HasCallStack):
99− error, called at example/Main.hs:47:10 in main:Main
100− fError, called at example/Main.hs:43:11 in main:Main
101− f10, called at example/Main.hs:40:6 in main:Main
102− f9, called at example/Main.hs:37:11 in main:Main
103− f8, called at example/Main.hs:33:16 in main:Main
104− f7, called at example/Main.hs:29:11 in main:Main
105− f6, called at example/Main.hs:25:15 in main:Main
106− f5, called at example/Main.hs:21:8 in main:Main
107− f4, called at example/Main.hs:17:6 in main:Main
108− f3, called at example/Main.hs:13:6 in main:Main
109− f2, called at example/Main.hs:10:6 in main:Main
110− f1, called at example/Main.hs:7:14 in main:Main
111− main, called at example/Main.hs:7:1 in main:Main
93+ error, called at example/Main.hs:40:10 in main:Main
94+ fError, called at example/Main.hs:36:11 in main:Main
95+ f8, called at example/Main.hs:32:16 in main:Main
96+ f7, called at example/Main.hs:28:11 in main:Main
97+ f6, called at example/Main.hs:24:15 in main:Main
98+ f5, called at example/Main.hs:20:8 in main:Main
99+ f4, called at example/Main.hs:16:6 in main:Main
100+ f3, called at example/Main.hs:12:6 in main:Main
101+ f2, called at example/Main.hs:9:6 in main:Main
102+ f1, called at example/Main.hs:6:14 in main:Main
103+ main, called at example/Main.hs:6:1 in main:Main
112104```
113105
114106Great!!!
example/Main.hs+3−9
@@ -18,10 +18,10 @@ f3 = f4 0
1818
1919-- HsQualTy
2020f4 :: Show a => a -> Int
21−f4 n = f5 (show n) 0
21+f4 _ = f5 0 0
2222
2323-- HsFunTy
24−f5 :: String -> Int -> Int
24+f5 :: Int -> Int -> Int
2525f5 _ _ = head f6
2626
2727-- HsListTy
@@ -34,13 +34,7 @@ f7 = (fromJust f8, fromJust f8)
3434
3535-- HsAppTy
3636f8 :: Maybe Int
37−f8 = Just f9
38−
39−f9 :: Int
40−f9 = f10
41− where
42− f10 :: Int
43− f10 = fError
37+f8 = Just fError
4438
4539-- HsTyVar
4640fError :: Int
haskell-stack-trace-plugin.cabal+16−14
@@ -1,6 +1,6 @@
11cabal-version: 2.4
22name: haskell-stack-trace-plugin
3−version: 0.1.3.0
3+version: 0.1.1.0
44synopsis: haskell-stack-trace-plugin
55description:
66 This plugin allow implicitly add HasCallStack class to every top-level function for all module. Hence, we can to get completely continuous call stack.
@@ -12,15 +12,15 @@ bug-reports:
1212license: MIT
1313license-file: LICENSE
1414author: Shinya Yamaguchi
15−maintainer: a@wado.dev
16−copyright: 2018-2021 Shinya Yamaguchi
15+maintainer: ingronze@gmail.com
16+copyright: 2018-2020 Shinya Yamaguchi
1717category: Compiler Plugin, Development, Debug
1818build-type: Simple
1919extra-source-files:
2020 CHANGELOG.md
2121 Readme.md
2222
23−tested-with: GHC ==8.6.5 || ==8.8.4 || ==8.10.4 || ==9.0.1
23+tested-with: GHC ==8.6.5
2424
2525source-repository head
2626 type: git
@@ -32,22 +32,24 @@ flag dev
3232 default: False
3333
3434common common-opts
35− build-depends: base >=4.12 && <4.18
35+ build-depends: base ^>=4.12
3636 default-language: Haskell2010
3737
3838library
3939 import: common-opts
4040 hs-source-dirs: src
41− build-depends: ghc ^>=8.6 || ^>=8.8 || ^>=8.10 || ^>=9.0 || ^>=9.2 || ^>=9.4
41+ build-depends: ghc ^>=8.6
4242 exposed-modules: StackTrace.Plugin
4343
4444 if flag(dev)
4545 ghc-options:
4646 -Wall -Werror -Wcompat -Wincomplete-uni-patterns
47− -Wnoncanonical-monad-instances -Wno-missing-home-modules
47+ -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances
48+ -Wno-missing-home-modules
4849
50+ -- -Wincomplete-record-updates
4951 else
50− ghc-options: -Wall
52+ ghc-options: -O2 -Wall
5153
5254test-suite test
5355 import: common-opts
@@ -55,22 +57,22 @@ test-suite test
5557 hs-source-dirs: test
5658 type: exitcode-stdio-1.0
5759 build-depends:
58− , bytestring >=0.10 && <0.12
59− , hspec ^>=2.8
60− , typed-process ^>=0.2
60+ , bytestring ^>=0.10
61+ , hspec ^>=2.7
62+ , typed-process ^>=0.2.6
6163
62− build-tool-depends: hspec-discover:hspec-discover ^>=2.8
64+ build-tool-depends: hspec-discover:hspec-discover ^>=2.7
6365 other-modules: StackTrace.PluginSpec
6466
6567 if flag(dev)
6668 ghc-options: -Wall -Werror
6769
6870 else
69− ghc-options: -Wall
71+ ghc-options: -O2 -Wall
7072
7173executable example
7274 import: common-opts
7375 main-is: Main.hs
7476 hs-source-dirs: example
75− ghc-options: -fplugin=StackTrace.Plugin -Wredundant-constraints
77+ ghc-options: -fplugin=StackTrace.Plugin
7678 build-depends: haskell-stack-trace-plugin
src/StackTrace/Plugin.hs+14−109
@@ -1,23 +1,11 @@
11{-# LANGUAGE RankNTypes #-}
22{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE CPP #-}
43module StackTrace.Plugin (plugin) where
54
65import Control.Arrow (first)
76import Data.Monoid (Any(Any, getAny))
8−import GHC.Types.SrcLoc
9−#if __GLASGOW_HASKELL__ >= 900
10−import GHC.Plugins
11−#else
12−
137import GhcPlugins
14−#endif
15−#if __GLASGOW_HASKELL__ >= 810
16−import GHC.Hs
17−#endif
18−#if __GLASGOW_HASKELL__ < 810
198import HsSyn
20−#endif
219
2210type Traversal s t a b
2311 = forall f. Applicative f =>
@@ -40,30 +28,13 @@ parsedPlugin _ _ pm = do
4028ghcStackModuleName :: ModuleName
4129ghcStackModuleName = mkModuleName "AutoImported.GHC.Stack"
4230
43−#if __GLASGOW_HASKELL__ < 810
44−importDeclQualified :: Bool
45−importDeclQualified = True
46−#else
47−importDeclQualified :: ImportDeclQualifiedStyle
48−importDeclQualified = QualifiedPre
49−#endif
50−
5131ghcStackImport :: Located (ImportDecl (GhcPass p))
5232ghcStackImport =
53− L srcSpan $
33+ noLoc $
5434 (simpleImportDecl $ mkModuleName "GHC.Stack")
55− { ideclQualified = importDeclQualified, ideclAs = Just $ noLoc ghcStackModuleName }
56− where
57− -- This is for GHC-9 related problems. @noLoc@ causes GHC to throw warnings
58− -- about unused imports. Even if the import is used
59− -- See: https://github.com/waddlaw/haskell-stack-trace-plugin/issues/16
60− srcSpan = RealSrcSpan (realSrcLocSpan $ mkRealSrcLoc "haskell-stack-trace-plugin:very-unique-file-name-to-avoid-collision" 1 1) Nothing
61−
62−#if __GLASGOW_HASKELL__ >= 900
63−updateHsModule :: HsModule -> HsModule
64−#else
35+ {ideclQualified = True, ideclAs = Just $ noLoc ghcStackModuleName}
36+
6537updateHsModule :: HsModule GhcPs -> HsModule GhcPs
66−#endif
6738updateHsModule hsm =
6839 hsm {hsmodImports = hsmodImports', hsmodDecls = hsmodDecls'}
6940 where
@@ -85,6 +56,7 @@ updateHsModule hsm =
8556 astTraversal :: Traversal' (LHsDecl GhcPs) (HsType GhcPs)
8657 astTraversal = updateHsmodDecl
8758 . updateHsDecl
59+ . updateSig
8860 . updateLHsSigWsType
8961 . updateLHsSigType
9062 . updateLHsType
@@ -93,56 +65,10 @@ updateHsModule hsm =
9365updateHsmodDecl :: Traversal' (LHsDecl GhcPs) (HsDecl GhcPs)
9466updateHsmodDecl = traverse
9567
96−updateHsDecl :: Traversal' (HsDecl GhcPs) (LHsSigWcType GhcPs)
97−updateHsDecl f (SigD xSig s) = SigD xSig <$> updateSig f s
98−updateHsDecl f (ValD xVal hsBind) = ValD xVal <$> updateHsBind f hsBind
68+updateHsDecl :: Traversal' (HsDecl GhcPs) (Sig GhcPs)
69+updateHsDecl f (SigD xSig s) = SigD xSig <$> f s
9970updateHsDecl _ sig = pure sig
10071
101−updateHsBind :: Traversal' (HsBind GhcPs) (LHsSigWcType GhcPs)
102−updateHsBind f bind@FunBind {} = (\x -> bind {fun_matches = x}) <$> updateMatchGroup f (fun_matches bind)
103−updateHsBind _ bind = pure bind
104−
105−updateMatchGroup :: Traversal' (MatchGroup GhcPs (LHsExpr GhcPs)) (LHsSigWcType GhcPs)
106−updateMatchGroup f mg@MG {} = (\x -> mg {mg_alts = x}) <$> updateLLMatch f (mg_alts mg)
107−#if __GLASGOW_HASKELL__ < 900
108−updateMatchGroup _ mg = pure mg
109−#endif
110−
111−updateLocated :: Functor f => (a -> b -> f c) -> a -> Located b -> f (Located c)
112−updateLocated f g (L l e) = L l <$> f g e
113−
114−updateLLMatch :: Traversal' (Located [LMatch GhcPs (LHsExpr GhcPs)]) (LHsSigWcType GhcPs)
115−updateLLMatch = updateLocated updateLMatches
116−
117−updateLMatches :: Traversal' [LMatch GhcPs (LHsExpr GhcPs)] (LHsSigWcType GhcPs)
118−updateLMatches f = traverse (updateLocated updateMatch f)
119−
120−updateMatch :: Traversal' (Match GhcPs (LHsExpr GhcPs)) (LHsSigWcType GhcPs)
121−updateMatch f m@Match {} = (\x -> m {m_grhss = x}) <$> updateGrhss f (m_grhss m)
122−#if __GLASGOW_HASKELL__ < 900
123−updateMatch _ m = pure m
124−#endif
125−
126−updateGrhss :: Traversal' (GRHSs GhcPs (LHsExpr GhcPs)) (LHsSigWcType GhcPs)
127−updateGrhss f grhss@GRHSs {} = (\x -> grhss {grhssLocalBinds = x}) <$> updateLHsLocalBinds f (grhssLocalBinds grhss)
128−#if __GLASGOW_HASKELL__ < 900
129−updateGrhss _ grhss = pure grhss
130−#endif
131−
132−updateLHsLocalBinds :: Traversal' (LHsLocalBinds GhcPs) (LHsSigWcType GhcPs)
133−updateLHsLocalBinds = updateLocated updateLocalBinds
134−
135−updateLocalBinds :: Traversal' (HsLocalBinds GhcPs) (LHsSigWcType GhcPs)
136−updateLocalBinds f (HsValBinds xHsValBinds hsValBindsLR) = HsValBinds xHsValBinds <$> updateHsValBindsLR f hsValBindsLR
137−updateLocalBinds _ hsValBinds = pure hsValBinds
138−
139−updateHsValBindsLR :: Traversal' (HsValBindsLR GhcPs GhcPs) (LHsSigWcType GhcPs)
140−updateHsValBindsLR f (ValBinds xValBinds lHsBindsLR lSigs) = ValBinds xValBinds lHsBindsLR <$> updateLSigs f lSigs
141−updateHsValBindsLR _ valBinds = pure valBinds
142−
143−updateLSigs :: Traversal' [LSig GhcPs] (LHsSigWcType GhcPs)
144−updateLSigs f = traverse (updateLocated updateSig f)
145−
14672updateSig :: Traversal' (Sig GhcPs) (LHsSigWcType GhcPs)
14773updateSig f (TypeSig xSig ls t) = TypeSig xSig ls <$> f t
14874updateSig _ sig = pure sig
@@ -150,62 +76,41 @@ updateSig _ sig = pure sig
15076updateLHsSigWsType :: Traversal' (LHsSigWcType GhcPs) (LHsSigType GhcPs)
15177updateLHsSigWsType f lhs@HsWC {} =
15278 (\x -> lhs {hswc_body = x}) <$> f (hswc_body lhs)
153−#if __GLASGOW_HASKELL__ < 900
15479updateLHsSigWsType _ lhs = pure lhs
155−#endif
15680
15781updateLHsSigType :: Traversal' (LHsSigType GhcPs) (LHsType GhcPs)
15882updateLHsSigType f lhs@HsIB {} =
15983 (\x -> lhs {hsib_body = x}) <$> f (hsib_body lhs)
160−#if __GLASGOW_HASKELL__ < 900
16184updateLHsSigType _ lhs = pure lhs
162−#endif
16385
16486updateLHsType :: Traversal' (LHsType GhcPs) (HsType GhcPs)
16587updateLHsType = traverse
16688
16789-- Main process
16890updateHsType :: HsType GhcPs -> (Any, HsType GhcPs)
169−updateHsType ty@(HsQualTy xty ctxt body) =
170− if hasHasCallStack (unLoc ctxt)
171− then pure ty
172− else flagASTModified $ HsQualTy xty (fmap appendHSC ctxt) body
91+updateHsType (HsQualTy xty ctxt body) =
92+ flagASTModified $ HsQualTy xty (fmap appendHSC ctxt) body
17393updateHsType ty@HsTyVar {} =
174− flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC []) (noLoc ty)
94+ flagASTModified $ HsQualTy noExt (noLoc $ appendHSC []) (noLoc ty)
17595updateHsType ty@HsAppTy {} =
176− flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC []) (noLoc ty)
96+ flagASTModified $ HsQualTy noExt (noLoc $ appendHSC []) (noLoc ty)
17797updateHsType ty@HsFunTy {} =
178− flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC []) (noLoc ty)
98+ flagASTModified $ HsQualTy noExt (noLoc $ appendHSC []) (noLoc ty)
17999updateHsType ty@HsListTy {} =
180− flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC []) (noLoc ty)
100+ flagASTModified $ HsQualTy noExt (noLoc $ appendHSC []) (noLoc ty)
181101updateHsType ty@HsTupleTy {} =
182− flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC []) (noLoc ty)
102+ flagASTModified $ HsQualTy noExt (noLoc $ appendHSC []) (noLoc ty)
183103updateHsType ty = pure ty
184104
185−#if __GLASGOW_HASKELL__ < 810
186−xQualTy :: NoExt
187−xQualTy = noExt
188−#else
189−xQualTy :: NoExtField
190−xQualTy = NoExtField
191−#endif
192−
193105flagASTModified :: a -> (Any, a)
194106flagASTModified a = (Any True, a)
195107
196108appendHSC :: HsContext GhcPs -> HsContext GhcPs
197109appendHSC cs = mkHSC : cs
198110
199−hasHasCallStack :: HsContext GhcPs -> Bool
200−hasHasCallStack = any (checkHsType . unLoc)
201− where
202− checkHsType :: HsType GhcPs -> Bool
203− checkHsType (HsTyVar _ _ lid) = unLoc lid == (mkRdrUnqual $ mkClsOcc "HasCallStack")
204− checkHsType _ = False
205−
206111-- make HasCallStack => constraint
207112mkHSC :: LHsType GhcPs
208−mkHSC = noLoc $ HsTyVar xQualTy NotPromoted lId
113+mkHSC = noLoc $ HsTyVar noExt NotPromoted lId
209114
210115lId :: Located (IdP GhcPs)
211116lId = noLoc $ mkRdrQual ghcStackModuleName $ mkClsOcc "HasCallStack"
test/StackTrace/PluginSpec.hs+1−1
@@ -9,7 +9,7 @@ import System.Process.Typed
99spec :: Spec
1010spec = do
1111 output <- runIO exe
12− expected <- runIO $ BL.readFile "test/resource/ghc.output"
12+ expected <- runIO $ BL.readFile "test/resource/ghc86.output"
1313 it "integration test" $ output `shouldBe` expected
1414
1515
test/resource/ghc.output → test/resource/ghc86.outputrenamed+2−4
@@ -1,9 +1,7 @@
11example: fError
22CallStack (from HasCallStack):
3− error, called at example/Main.hs:47:10 in main:Main
4− fError, called at example/Main.hs:43:11 in main:Main
5− f10, called at example/Main.hs:40:6 in main:Main
6− f9, called at example/Main.hs:37:11 in main:Main
3+ error, called at example/Main.hs:41:10 in main:Main
4+ fError, called at example/Main.hs:37:11 in main:Main
75 f8, called at example/Main.hs:33:16 in main:Main
86 f7, called at example/Main.hs:29:11 in main:Main
97 f6, called at example/Main.hs:25:15 in main:Main