summaryrefslogtreecommitdiff
path: root/testsuite/tests/simplCore/should_run/T21575.hs
blob: 976483f963011bc16a7f6214812e388eb2885c16 (plain)
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{-# LANGUAGE CPP #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}

-- 0 => use unsafeCoerce
-- 1 => use withDict
#define WITH_DICT 1

module Main (main) where

import Control.Monad (unless)
import qualified Data.Map as M
import Data.Map (Map)

#if WITH_DICT
import GHC.Exts (withDict)
#else
import Unsafe.Coerce (unsafeCoerce)
#endif

main :: IO ()
main = do
  testCase (give Normal (toJSON (Foo Bar)))
           (Object (M.fromList [("Foo",String "Bar")]))
  testCase (give ViaShow (toJSON (Foo Bar)))
           (Object (M.fromList [("Foo",String "SHOWBAR")]))
  putStrLn "All tests passed!"

{-
toJSONBar :: Given Style => Bar -> Value

  give Normal (\gd -> toJSONBar gd e)
  --> withDict @Style @(Given Style) Normal (toJSON e)
  --> toJSONBar ((Normal |> co) :: Given Style) e

  give Normal (\gd -> toJSONBar gd e')
  --> toJSONBar ((ViaShow |> co) :: Given Style) e'

--------- With new cast ------------

  give Normal (\gd -> toJSONBar gd e)
  --> withDict @Style @(Given Style) Normal (\gd -> toJSONBar gd e)
  --> ((\gd -> toJSONBar gd e) |> co) Normal
  --> (\gd' -> toJSonBar (gd' |> sym (co[1])) e) Normal
  --> toJSONBar (Normal |> co') e   -- Boo!

-}

testCase :: (Eq a, Show a) => a -> a -> IO ()
testCase expected actual =
  unless (expected == actual) $
    error $ unlines
      [ ""
      , "Expected: " ++ show expected
      , "Actual:   " ++ show actual
      ]

class Given a where
  given :: a

give :: forall a r. a -> (Given a => r) -> r
#if WITH_DICT
give = withDict @a @(Given a)
#else
give a k = unsafeCoerce (Gift k :: Gift a r) a

newtype Gift a r = Gift (Given a => r)
#endif

data Foo = Foo Bar

instance Show Foo where
  show _ = "SHOWFOO"

data Bar = Bar | BarBar

instance Show Bar where
  show _ = "SHOWBAR"

----------------------------------------------------------------------------
-- ToJSON instances
----------------------------------------------------------------------------

instance Given Style => ToJSON Foo where
  toJSON (Foo x) = Object $ M.singleton "Foo" (toJSON x)

instance Given Style => ToJSON Bar where
  toJSON x = case given of
    Normal -> String $ case x of
                Bar    -> "Bar"
                BarBar -> "BarBar"
    ViaShow -> String $ show x

data Style = Normal | ViaShow

----------------------------------------------------------------------------
-- Minimized aeson
----------------------------------------------------------------------------

class ToJSON a where
  toJSON :: a -> Value

data Value
  = Object !(Map String Value)
  | String !String
  deriving (Eq, Show)