The main way to set a new data type in Haskell is to use the data construct. However, there is also a newtype
. Practicing Haskell programmers use the newtype
construct all the time, the popular hlint hlint
suggests replacing data
with newtype
if possible.
But why?
At first I planned this article for newbies. Indeed, the newtype
construct is mentioned in the first chapters of Haskell tutorials. It seems to be a simple idea: we limit the presentation for the data type and gain speed. In various sources you can find references that newtype
saves on nesting of pointers. But I didn’t find a detailed analysis of what actually happens with this construction in the compiler and why it is so cool and necessary. To fill these gaps, I decided to write an article on Habr.
So, we need the haskell stack and basic knowledge of the Haskell and GHC execution model (we know what lazy calculations are, thunks (uncomputed objects), we heard a little about the stack and the GHC heap).
The syntax for the newtype
construct is exactly the same as the data construct, except that a newtype
can have only one constructor and only one boxed (boxed type) field inside.
-- | data MyValDL = MyValDLC Int -- | , thunk' -- ( Int) data MyValDS = MyValDSC !Int -- | , -- newtype newtype MyValN = MyValNC Int
By the way, all sorts of record syntax and phantom types also work:
newtype MyFunnyA abc = MyFunnyA { getA :: a }
But what is the difference between MyValDL
( MyValDS
) and MyValN
?
The Haskell'98 report states that the newtype
construct introduces a new type, whose representation is identical to the existing one. That is, Int
and MyValN
isomorphic. But is it not so for data
types? It turns out no. The fact is that in Haskell there are “lifted” and “not lifted” types. For all types declared with data
, an additional element "bottom" (bottom, or) is added - they become raised (for the program, the "bottom" is undefined
). This means that " MyValDLC ⊥ :: MyValDL
" and " ⊥ :: MyValDL
" are different meanings. Unlike data
, a newtype
type is not raised (unlifted type), which means ⊥ :: MyValN
“borrowed” from a nested type (via MyValN ⊥
).
We can say that for a compiler, a raised type means an extra layer of pointers (a pointer can refer to an embedded object, or to the bottom (undefined)). For a programmer, this means that if the data
field of the constructor may contain undefined
, all is not lost: until we touch this field, the program will not break. A non-computed field, on the other hand, can be a place of memory leakage (a series of thunks). With strict MyValDS
the situation is a bit more complicated: it seems that MyValDSC ⊥
immediately computed to ⊥
, but the semantics of these two constructors are the same. By the way, therefore, professionals recommend declaring all fields in data constructors to be strict, unless there is a real need to use the field lazily - this way you can avoid long hours of searching for memory leaks.
The Haskell wiki has an excellent set of examples that illustrate the difference between data and newtype
; I will give them here, adjusted for free translation and my type names:
-- ( ), -- xDL :: Int xDL = case MyValDLC undefined of MyValDLC _ -> 1 -- 1 -- , undefined xDS :: Int xDS = case MyValDSC undefined of MyValDSC _ -> 1 -- undefined -- newtype Int, 1 -- ( , , . yInt) xN :: Int xN = case MyValNC undefined of MyValNC _ -> 1 -- 1 -- yDL :: Int yDL = case undefined of MyValDLC _ -> 1 -- undefined -- yDS :: Int yDS = case undefined of MyValDSC _ -> 1 -- undefined -- newtype Int, MyValN -- ! yN :: Int yN = case undefined of MyValNC _ -> 1 -- 1 -- Int: -- case undefined, -- , -- yInt :: Int yInt = case (undefined :: Int) of _ -> 1 -- 1
The above description is my interpretation of the Haskell wiki . But we will not stop at this and consider a few more questions.
Requiring the same representation of the original type and its newtype
wrapper for the compiler means that:
data A
" and " newtype NA = NA
" type systems, these are different types.NA
" and " A
" are the same.GHC works with types on two levels: Haskell’s “visible” type system, and representation types. The visible type system is what we work with in Haskell programming. However, at some point, the compiler converts the Haskell types into a machine representation. It often happens that two different types in Haskell can have the same representation in machine code. In the modern GHC, with the help of the role system , it is possible to compare types not only nominally, but also according to their presentation. This made it possible to implement the free type conversion mechanism (visible only at the level of the Haskell type system) in the Data.Type.Coercion and Data.Coerce modules .
Considering the above, the general idea of ​​implementing newtype
is obvious: all of the packed values ​​in Haskell are represented as a description with a pointer to the constructor (object info tables); therefore, the value of a newtype
can in its description use a pointer directly to the constructor of the nested value; it turns out something like the type
synonyms, only at a lower level.
Every Haskell programmer knows that GHC does not compile the source code into an assembler right away, but produces a complex series of code conversions in several stages, with optimizations on almost every one of them. First, the Haskell syntax tree is transformed into a simplified version of the language - GHC Core (which is based on system F). Then Core is converted to a functional STG (Spineless Tagless G-machine), then to an imperative C--
(special intermediate language with support for exception handling and garbage collection), and from there to various ways into an assembler.
It seems that the statement that newtype
constructors "disappear" at run time is well known. However, it turned out to be quite difficult to understand how this happens. The description of the STG on the GHC website makes us understand that the STG already operates with only representative types, that is, the newtype
should be lost to it. Another GHC wiki page hints that some types are always visible, and some only for type checker (the latter, by the way, seem to have the tc prefix at different levels of the generated code). To find out for sure what happens with newtype
types, I decided to look at all the intermediate stages of the compiled code with the following example:
newtype MyNewtypeStruct = MyNewtypeConstr { unNewtypeStruct :: Int } data MyDataStruct = MyDataConstr { unDataStruct :: Int } ntToD :: MyNewtypeStruct -> MyDataStruct ntToD x = case x of MyNewtypeConstr y -> MyDataConstr y dToNt :: MyDataStruct -> MyNewtypeStruct dToNt x = case x of MyDataConstr y -> MyNewtypeConstr y
The result was not long in coming at the first stage:
stack exec ghc-core -- --no-asm Main.hs -fforce-recomp -O0 -fno-enable-rewrite-rules
The ghc-core
program, available in the hackage package of the same name, displays a slightly cleaned GHC Core. Already at this stage, all occurrences of MyNewtypeConstr
are replaced by cast
operations, while MyDataConstr
honestly remains in its place:
unNewtypeStruct1_rG2 :: MyNewtypeStruct -> MyNewtypeStruct unNewtypeStruct1_rG2 = \ (ds_dGl :: MyNewtypeStruct) -> ds_dGl unNewtypeStruct :: MyNewtypeStruct -> Int unNewtypeStruct = unNewtypeStruct1_rG2 `cast` (<MyNewtypeStruct>_R -> N:MyNewtypeStruct[0] :: ((MyNewtypeStruct -> MyNewtypeStruct) :: *) ~R# ((MyNewtypeStruct -> Int) :: *)) unDataStruct :: MyDataStruct -> Int unDataStruct = \ (ds_dGj :: MyDataStruct) -> case ds_dGj of _ [Occ=Dead] { MyDataConstr ds1_dGk -> ds1_dGk } ntToD :: MyNewtypeStruct -> MyDataStruct ntToD = MyDataConstr `cast` (Sym N:MyNewtypeStruct[0] -> <MyDataStruct>_R :: ((Int -> MyDataStruct) :: *) ~R# ((MyNewtypeStruct -> MyDataStruct) :: *)) dToNt :: MyDataStruct -> MyNewtypeStruct dToNt = \ (x_awb :: MyDataStruct) -> case x_awb of _ [Occ=Dead] { MyDataConstr y_awc -> y_awc `cast` (Sym N:MyNewtypeStruct[0] :: (Int :: *) ~R# (MyNewtypeStruct :: *))
The next stage is STG, it can be viewed with the following command:
stack exec ghc -- Main.hs -fforce-recomp -O0 -fno-enable-rewrite-rules -ddump-stg > Main.stg
It is not much different from Core, except for the interesting detail: Main.MyDataConstr
is defined explicitly in the generated code, and Main.MyNewtypeConstr
.
Main.MyDataConstr :: GHC.Types.Int -> Main.MyDataStruct [GblId[DataCon], Arity=1, Caf=NoCafRefs, Str=DmdType <L,U>m, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1];
At the --
level, you can find constructions such as Main.$tc'MyNewtypeConstr
and Main.$tc'MyDataConstr
, but Main.MyDataConstr
does not find a newtype
. Apparently, $tc
(from the word Type Checker) is another hint of types that are used only at the type checking level.
As we can see, already at the GHC Core transformation stage, newtype
constructors are replaced with primitive type conversions. At the C--
level, you can compare the low-level imperative code Main.unNewtypeStruct_entry()
and Main.unDataStruct_entry()
to make sure that unNewtypeStruct
does virtually nothing, unlike unDataStruct
.
All output levels can be viewed using several commands:
stack exec ghc -- ${filename}.hs -fforce-recomp -O0 -fno-enable-rewrite-rules -fllvm -keep-llvm-files stack exec ghc-core -- --no-asm --no-syntax ${filename}.hs -fforce-recomp -O0 -fno-enable-rewrite-rules > ${filename}.hcr stack exec ghc -- ${filename}.hs -fforce-recomp -O0 -fno-enable-rewrite-rules -ddump-stg > ${filename}.stg stack exec ghc -- ${filename}.hs -fforce-recomp -O0 -fno-enable-rewrite-rules -ddump-opt-cmm > ${filename}.cmm
The output formatted by me is under a cat. I left only more or less interesting parts (the text is already too much).
-- CORE ------------------------------------------------------------------------ unNewtypeStruct1_rG2 :: MyNewtypeStruct -> MyNewtypeStruct unNewtypeStruct1_rG2 = \ (ds_dGl :: MyNewtypeStruct) -> ds_dGl unNewtypeStruct :: MyNewtypeStruct -> Int unNewtypeStruct = unNewtypeStruct1_rG2 `cast` (<MyNewtypeStruct>_R -> N:MyNewtypeStruct[0] :: ((MyNewtypeStruct -> MyNewtypeStruct) :: *) ~R# ((MyNewtypeStruct -> Int) :: *)) unDataStruct :: MyDataStruct -> Int unDataStruct = \ (ds_dGj :: MyDataStruct) -> case ds_dGj of _ [Occ=Dead] { MyDataConstr ds1_dGk -> ds1_dGk } ntToD :: MyNewtypeStruct -> MyDataStruct ntToD = MyDataConstr `cast` (Sym N:MyNewtypeStruct[0] -> <MyDataStruct>_R :: ((Int -> MyDataStruct) :: *) ~R# ((MyNewtypeStruct -> MyDataStruct) :: *)) dToNt :: MyDataStruct -> MyNewtypeStruct dToNt = \ (x_awb :: MyDataStruct) -> case x_awb of _ [Occ=Dead] { MyDataConstr y_awc -> y_awc `cast` (Sym N:MyNewtypeStruct[0] :: (Int :: *) ~R# (MyNewtypeStruct :: *)) -- ... $tc'MyNewtypeConstr1_rGD :: TrName $tc'MyNewtypeConstr1_rGD = TrNameS "'MyNewtypeConstr"# $tc'MyDataConstr1_rGF :: TrName $tc'MyDataConstr1_rGF = TrNameS "'MyDataConstr"# -- .. $tcMyNewtypeStruct1_rGE :: TrName $tcMyNewtypeStruct1_rGE = TrNameS "MyNewtypeStruct"# $tcMyDataStruct1_rGG :: TrName $tcMyDataStruct1_rGG = TrNameS "MyDataStruct"# -- ... -- STG ------------------------------------------------------------------------- unNewtypeStruct1_rG2 :: Main.MyNewtypeStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = sat-only \r srt:SRT:[] [ds_sQ7] ds_sQ7; Main.unNewtypeStruct :: Main.MyNewtypeStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] unNewtypeStruct1_rG2 eta_B1; Main.unDataStruct :: Main.MyDataStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [ds_sQ8] case ds_sQ8 of _ [Occ=Dead] { Main.MyDataConstr ds1_sQa [Occ=Once] -> ds1_sQa; }; Main.ntToD :: Main.MyNewtypeStruct -> Main.MyDataStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; Main.dToNt :: Main.MyDataStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [x_sQb] case x_sQb of _ [Occ=Dead] { Main.MyDataConstr y_sQd [Occ=Once] -> y_sQd; }; -- ... constructors seem to be defined exactly the same way for both types ... -- There is one more definition in the STG dump Main.MyDataConstr :: GHC.Types.Int -> Main.MyDataStruct [GblId[DataCon], Arity=1, Caf=NoCafRefs, Str=DmdType <L,U>m, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; -- C-- ------------------------------------------------------------------------- unNewtypeStruct1_rG2_entry() // [R2] { [(cQj, unNewtypeStruct1_rG2_info: const 4294967301; const 0; const 15;)] } {offset cQj: _sQ8::P64 = R2; goto cQl; cQl: R1 = _sQ8::P64 & (-8); call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } Main.unNewtypeStruct_entry() // [R2] { [(cQv, Main.unNewtypeStruct_info: const 4294967301; const 0; const 15;)] } {offset cQv: _B1::P64 = R2; goto cQx; cQx: R2 = _B1::P64; call unNewtypeStruct1_rG2_info(R2) args: 8, res: 0, upd: 8; } } Main.unDataStruct_entry() // [R2] { [(cQJ, block_cQJ_info: const 0; const 32;), (cQM, Main.unDataStruct_info: const 4294967301; const 0; const 15;)] } {offset cQM: _sQ9::P64 = R2; if ((Sp + -8) < SpLim) goto cQN; else goto cQO; cQN: R2 = _sQ9::P64; R1 = Main.unDataStruct_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cQO: I64[Sp - 8] = block_cQJ_info; R1 = _sQ9::P64; Sp = Sp - 8; if (R1 & 7 != 0) goto cQJ; else goto cQK; cQK: call (I64[R1])(R1) returns to cQJ, args: 8, res: 8, upd: 8; cQJ: _sQa::P64 = R1; _sQb::P64 = P64[_sQa::P64 + 7]; R1 = _sQb::P64 & (-8); Sp = Sp + 8; call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } section ""data" . $tc'MyNewtypeConstr1_rGD_closure" { $tc'MyNewtypeConstr1_rGD_closure: const GHC.Types.TrNameS_static_info; const cRI_str; } section ""data" . Main.$tc'MyNewtypeConstr_closure" { Main.$tc'MyNewtypeConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyNewtypeConstr1_rGD_closure+1; const 10344856529254187725; const 4384341159368653246; const 3; } section ""data" . $tc'MyDataConstr1_rGF_closure" { $tc'MyDataConstr1_rGF_closure: const GHC.Types.TrNameS_static_info; const cRU_str; } section ""data" . Main.$tc'MyDataConstr_closure" { Main.$tc'MyDataConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyDataConstr1_rGF_closure+1; const 12971553621823397951; const 6686958652479025466; const 3; } section ""data" . Main.MyDataConstr_closure" { Main.MyDataConstr_closure: const Main.MyDataConstr_info; } Main.MyDataConstr_entry() // [R2] { [(cSE, Main.MyDataConstr_info: const 4294967301; const 0; const 15;)] } {offset cSE: _B1::P64 = R2; goto cSG; cSG: Hp = Hp + 16; if (Hp > I64[BaseReg + 856]) goto cSI; else goto cSH; cSI: I64[BaseReg + 904] = 16; goto cSF; cSF: R2 = _B1::P64; R1 = Main.MyDataConstr_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cSH: I64[Hp - 8] = Main.MyDataConstr_con_info; P64[Hp] = _B1::P64; _cSD::P64 = Hp - 7; R1 = _cSD::P64; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_con_entry() // [] { [(cSN, Main.MyDataConstr_con_info: const iSP_str-Main.MyDataConstr_con_info; const 1; const 2;)] } {offset cSN: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_static_entry() // [] { [(cSO, Main.MyDataConstr_static_info: const iSQ_str-Main.MyDataConstr_static_info; const 1; const 7;)] } {offset cSO: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } -- LLVM ------------------------------------------------------------------------ %Main_zdtczqMyNewtypeConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyNewtypeConstr_closure$def = internal global %Main_zdtczqMyNewtypeConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGD_closure_struct* @rGD_closure$def to i64),i64 1), i64 -8101887544455363891, i64 4384341159368653246, i64 3}> @Main_zdtczqMyNewtypeConstr_closure = alias i8* bitcast (%Main_zdtczqMyNewtypeConstr_closure_struct* @Main_zdtczqMyNewtypeConstr_closure$def to i8*) %Main_zdtcMyNewtypeStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyNewtypeStruct_closure$def = internal global %Main_zdtcMyNewtypeStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGE_closure_struct* @rGE_closure$def to i64),i64 1), i64 2735651172251469986, i64 2399541496478989519, i64 3}> @Main_zdtcMyNewtypeStruct_closure = alias i8* bitcast (%Main_zdtcMyNewtypeStruct_closure_struct* @Main_zdtcMyNewtypeStruct_closure$def to i8*) %Main_zdtczqMyDataConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyDataConstr_closure$def = internal global %Main_zdtczqMyDataConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGF_closure_struct* @rGF_closure$def to i64),i64 1), i64 -5475190451886153665, i64 6686958652479025466, i64 3}> @Main_zdtczqMyDataConstr_closure = alias i8* bitcast (%Main_zdtczqMyDataConstr_closure_struct* @Main_zdtczqMyDataConstr_closure$def to i8*) %Main_zdtcMyDataStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyDataStruct_closure$def = internal global %Main_zdtcMyDataStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGG_closure_struct* @rGG_closure$def to i64),i64 1), i64 5826051442705447975, i64 -4331072423017222539, i64 3}> @Main_zdtcMyDataStruct_closure = alias i8* bitcast (%Main_zdtcMyDataStruct_closure_struct* @Main_zdtcMyDataStruct_closure$def to i8*) %Main_MyDataConstr_closure_struct = type <{i64}> @Main_MyDataConstr_closure$def = internal global %Main_MyDataConstr_closure_struct<{i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i64)}> @Main_MyDataConstr_closure = alias i8* bitcast (%Main_MyDataConstr_closure_struct* @Main_MyDataConstr_closure$def to i8*) @Main_MyDataConstr_info = internal alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i8*) define internal ghccc void @Main_MyDataConstr_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 4294967301, i64 0, i64 15}> { cW0: ... ret void } @Main_MyDataConstr_con_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i8*) define ghccc void @Main_MyDataConstr_con_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWK_str_struct* @iWK_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i64)),i64 0), i64 1, i64 2}> { ... } @Main_MyDataConstr_static_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i8*) define ghccc void @Main_MyDataConstr_static_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWL_str_struct* @iWL_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i64)),i64 0), i64 1, i64 7}> { ... }
Main_zdtczqMyNewtypeConstr_closure_struct <{i64 ptrtoint (i8 * @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (% Main_zdtrModule_closure_struct * @ Main_zdtrModule_closure $ def to i64), i64 -- CORE ------------------------------------------------------------------------ unNewtypeStruct1_rG2 :: MyNewtypeStruct -> MyNewtypeStruct unNewtypeStruct1_rG2 = \ (ds_dGl :: MyNewtypeStruct) -> ds_dGl unNewtypeStruct :: MyNewtypeStruct -> Int unNewtypeStruct = unNewtypeStruct1_rG2 `cast` (<MyNewtypeStruct>_R -> N:MyNewtypeStruct[0] :: ((MyNewtypeStruct -> MyNewtypeStruct) :: *) ~R# ((MyNewtypeStruct -> Int) :: *)) unDataStruct :: MyDataStruct -> Int unDataStruct = \ (ds_dGj :: MyDataStruct) -> case ds_dGj of _ [Occ=Dead] { MyDataConstr ds1_dGk -> ds1_dGk } ntToD :: MyNewtypeStruct -> MyDataStruct ntToD = MyDataConstr `cast` (Sym N:MyNewtypeStruct[0] -> <MyDataStruct>_R :: ((Int -> MyDataStruct) :: *) ~R# ((MyNewtypeStruct -> MyDataStruct) :: *)) dToNt :: MyDataStruct -> MyNewtypeStruct dToNt = \ (x_awb :: MyDataStruct) -> case x_awb of _ [Occ=Dead] { MyDataConstr y_awc -> y_awc `cast` (Sym N:MyNewtypeStruct[0] :: (Int :: *) ~R# (MyNewtypeStruct :: *)) -- ... $tc'MyNewtypeConstr1_rGD :: TrName $tc'MyNewtypeConstr1_rGD = TrNameS "'MyNewtypeConstr"# $tc'MyDataConstr1_rGF :: TrName $tc'MyDataConstr1_rGF = TrNameS "'MyDataConstr"# -- .. $tcMyNewtypeStruct1_rGE :: TrName $tcMyNewtypeStruct1_rGE = TrNameS "MyNewtypeStruct"# $tcMyDataStruct1_rGG :: TrName $tcMyDataStruct1_rGG = TrNameS "MyDataStruct"# -- ... -- STG ------------------------------------------------------------------------- unNewtypeStruct1_rG2 :: Main.MyNewtypeStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = sat-only \r srt:SRT:[] [ds_sQ7] ds_sQ7; Main.unNewtypeStruct :: Main.MyNewtypeStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] unNewtypeStruct1_rG2 eta_B1; Main.unDataStruct :: Main.MyDataStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [ds_sQ8] case ds_sQ8 of _ [Occ=Dead] { Main.MyDataConstr ds1_sQa [Occ=Once] -> ds1_sQa; }; Main.ntToD :: Main.MyNewtypeStruct -> Main.MyDataStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; Main.dToNt :: Main.MyDataStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [x_sQb] case x_sQb of _ [Occ=Dead] { Main.MyDataConstr y_sQd [Occ=Once] -> y_sQd; }; -- ... constructors seem to be defined exactly the same way for both types ... -- There is one more definition in the STG dump Main.MyDataConstr :: GHC.Types.Int -> Main.MyDataStruct [GblId[DataCon], Arity=1, Caf=NoCafRefs, Str=DmdType <L,U>m, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; -- C-- ------------------------------------------------------------------------- unNewtypeStruct1_rG2_entry() // [R2] { [(cQj, unNewtypeStruct1_rG2_info: const 4294967301; const 0; const 15;)] } {offset cQj: _sQ8::P64 = R2; goto cQl; cQl: R1 = _sQ8::P64 & (-8); call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } Main.unNewtypeStruct_entry() // [R2] { [(cQv, Main.unNewtypeStruct_info: const 4294967301; const 0; const 15;)] } {offset cQv: _B1::P64 = R2; goto cQx; cQx: R2 = _B1::P64; call unNewtypeStruct1_rG2_info(R2) args: 8, res: 0, upd: 8; } } Main.unDataStruct_entry() // [R2] { [(cQJ, block_cQJ_info: const 0; const 32;), (cQM, Main.unDataStruct_info: const 4294967301; const 0; const 15;)] } {offset cQM: _sQ9::P64 = R2; if ((Sp + -8) < SpLim) goto cQN; else goto cQO; cQN: R2 = _sQ9::P64; R1 = Main.unDataStruct_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cQO: I64[Sp - 8] = block_cQJ_info; R1 = _sQ9::P64; Sp = Sp - 8; if (R1 & 7 != 0) goto cQJ; else goto cQK; cQK: call (I64[R1])(R1) returns to cQJ, args: 8, res: 8, upd: 8; cQJ: _sQa::P64 = R1; _sQb::P64 = P64[_sQa::P64 + 7]; R1 = _sQb::P64 & (-8); Sp = Sp + 8; call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } section ""data" . $tc'MyNewtypeConstr1_rGD_closure" { $tc'MyNewtypeConstr1_rGD_closure: const GHC.Types.TrNameS_static_info; const cRI_str; } section ""data" . Main.$tc'MyNewtypeConstr_closure" { Main.$tc'MyNewtypeConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyNewtypeConstr1_rGD_closure+1; const 10344856529254187725; const 4384341159368653246; const 3; } section ""data" . $tc'MyDataConstr1_rGF_closure" { $tc'MyDataConstr1_rGF_closure: const GHC.Types.TrNameS_static_info; const cRU_str; } section ""data" . Main.$tc'MyDataConstr_closure" { Main.$tc'MyDataConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyDataConstr1_rGF_closure+1; const 12971553621823397951; const 6686958652479025466; const 3; } section ""data" . Main.MyDataConstr_closure" { Main.MyDataConstr_closure: const Main.MyDataConstr_info; } Main.MyDataConstr_entry() // [R2] { [(cSE, Main.MyDataConstr_info: const 4294967301; const 0; const 15;)] } {offset cSE: _B1::P64 = R2; goto cSG; cSG: Hp = Hp + 16; if (Hp > I64[BaseReg + 856]) goto cSI; else goto cSH; cSI: I64[BaseReg + 904] = 16; goto cSF; cSF: R2 = _B1::P64; R1 = Main.MyDataConstr_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cSH: I64[Hp - 8] = Main.MyDataConstr_con_info; P64[Hp] = _B1::P64; _cSD::P64 = Hp - 7; R1 = _cSD::P64; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_con_entry() // [] { [(cSN, Main.MyDataConstr_con_info: const iSP_str-Main.MyDataConstr_con_info; const 1; const 2;)] } {offset cSN: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_static_entry() // [] { [(cSO, Main.MyDataConstr_static_info: const iSQ_str-Main.MyDataConstr_static_info; const 1; const 7;)] } {offset cSO: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } -- LLVM ------------------------------------------------------------------------ %Main_zdtczqMyNewtypeConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyNewtypeConstr_closure$def = internal global %Main_zdtczqMyNewtypeConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGD_closure_struct* @rGD_closure$def to i64),i64 1), i64 -8101887544455363891, i64 4384341159368653246, i64 3}> @Main_zdtczqMyNewtypeConstr_closure = alias i8* bitcast (%Main_zdtczqMyNewtypeConstr_closure_struct* @Main_zdtczqMyNewtypeConstr_closure$def to i8*) %Main_zdtcMyNewtypeStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyNewtypeStruct_closure$def = internal global %Main_zdtcMyNewtypeStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGE_closure_struct* @rGE_closure$def to i64),i64 1), i64 2735651172251469986, i64 2399541496478989519, i64 3}> @Main_zdtcMyNewtypeStruct_closure = alias i8* bitcast (%Main_zdtcMyNewtypeStruct_closure_struct* @Main_zdtcMyNewtypeStruct_closure$def to i8*) %Main_zdtczqMyDataConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyDataConstr_closure$def = internal global %Main_zdtczqMyDataConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGF_closure_struct* @rGF_closure$def to i64),i64 1), i64 -5475190451886153665, i64 6686958652479025466, i64 3}> @Main_zdtczqMyDataConstr_closure = alias i8* bitcast (%Main_zdtczqMyDataConstr_closure_struct* @Main_zdtczqMyDataConstr_closure$def to i8*) %Main_zdtcMyDataStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyDataStruct_closure$def = internal global %Main_zdtcMyDataStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGG_closure_struct* @rGG_closure$def to i64),i64 1), i64 5826051442705447975, i64 -4331072423017222539, i64 3}> @Main_zdtcMyDataStruct_closure = alias i8* bitcast (%Main_zdtcMyDataStruct_closure_struct* @Main_zdtcMyDataStruct_closure$def to i8*) %Main_MyDataConstr_closure_struct = type <{i64}> @Main_MyDataConstr_closure$def = internal global %Main_MyDataConstr_closure_struct<{i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i64)}> @Main_MyDataConstr_closure = alias i8* bitcast (%Main_MyDataConstr_closure_struct* @Main_MyDataConstr_closure$def to i8*) @Main_MyDataConstr_info = internal alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i8*) define internal ghccc void @Main_MyDataConstr_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 4294967301, i64 0, i64 15}> { cW0: ... ret void } @Main_MyDataConstr_con_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i8*) define ghccc void @Main_MyDataConstr_con_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWK_str_struct* @iWK_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i64)),i64 0), i64 1, i64 2}> { ... } @Main_MyDataConstr_static_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i8*) define ghccc void @Main_MyDataConstr_static_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWL_str_struct* @iWL_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i64)),i64 0), i64 1, i64 7}> { ... }
% -- CORE ------------------------------------------------------------------------ unNewtypeStruct1_rG2 :: MyNewtypeStruct -> MyNewtypeStruct unNewtypeStruct1_rG2 = \ (ds_dGl :: MyNewtypeStruct) -> ds_dGl unNewtypeStruct :: MyNewtypeStruct -> Int unNewtypeStruct = unNewtypeStruct1_rG2 `cast` (<MyNewtypeStruct>_R -> N:MyNewtypeStruct[0] :: ((MyNewtypeStruct -> MyNewtypeStruct) :: *) ~R# ((MyNewtypeStruct -> Int) :: *)) unDataStruct :: MyDataStruct -> Int unDataStruct = \ (ds_dGj :: MyDataStruct) -> case ds_dGj of _ [Occ=Dead] { MyDataConstr ds1_dGk -> ds1_dGk } ntToD :: MyNewtypeStruct -> MyDataStruct ntToD = MyDataConstr `cast` (Sym N:MyNewtypeStruct[0] -> <MyDataStruct>_R :: ((Int -> MyDataStruct) :: *) ~R# ((MyNewtypeStruct -> MyDataStruct) :: *)) dToNt :: MyDataStruct -> MyNewtypeStruct dToNt = \ (x_awb :: MyDataStruct) -> case x_awb of _ [Occ=Dead] { MyDataConstr y_awc -> y_awc `cast` (Sym N:MyNewtypeStruct[0] :: (Int :: *) ~R# (MyNewtypeStruct :: *)) -- ... $tc'MyNewtypeConstr1_rGD :: TrName $tc'MyNewtypeConstr1_rGD = TrNameS "'MyNewtypeConstr"# $tc'MyDataConstr1_rGF :: TrName $tc'MyDataConstr1_rGF = TrNameS "'MyDataConstr"# -- .. $tcMyNewtypeStruct1_rGE :: TrName $tcMyNewtypeStruct1_rGE = TrNameS "MyNewtypeStruct"# $tcMyDataStruct1_rGG :: TrName $tcMyDataStruct1_rGG = TrNameS "MyDataStruct"# -- ... -- STG ------------------------------------------------------------------------- unNewtypeStruct1_rG2 :: Main.MyNewtypeStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = sat-only \r srt:SRT:[] [ds_sQ7] ds_sQ7; Main.unNewtypeStruct :: Main.MyNewtypeStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] unNewtypeStruct1_rG2 eta_B1; Main.unDataStruct :: Main.MyDataStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [ds_sQ8] case ds_sQ8 of _ [Occ=Dead] { Main.MyDataConstr ds1_sQa [Occ=Once] -> ds1_sQa; }; Main.ntToD :: Main.MyNewtypeStruct -> Main.MyDataStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; Main.dToNt :: Main.MyDataStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [x_sQb] case x_sQb of _ [Occ=Dead] { Main.MyDataConstr y_sQd [Occ=Once] -> y_sQd; }; -- ... constructors seem to be defined exactly the same way for both types ... -- There is one more definition in the STG dump Main.MyDataConstr :: GHC.Types.Int -> Main.MyDataStruct [GblId[DataCon], Arity=1, Caf=NoCafRefs, Str=DmdType <L,U>m, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; -- C-- ------------------------------------------------------------------------- unNewtypeStruct1_rG2_entry() // [R2] { [(cQj, unNewtypeStruct1_rG2_info: const 4294967301; const 0; const 15;)] } {offset cQj: _sQ8::P64 = R2; goto cQl; cQl: R1 = _sQ8::P64 & (-8); call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } Main.unNewtypeStruct_entry() // [R2] { [(cQv, Main.unNewtypeStruct_info: const 4294967301; const 0; const 15;)] } {offset cQv: _B1::P64 = R2; goto cQx; cQx: R2 = _B1::P64; call unNewtypeStruct1_rG2_info(R2) args: 8, res: 0, upd: 8; } } Main.unDataStruct_entry() // [R2] { [(cQJ, block_cQJ_info: const 0; const 32;), (cQM, Main.unDataStruct_info: const 4294967301; const 0; const 15;)] } {offset cQM: _sQ9::P64 = R2; if ((Sp + -8) < SpLim) goto cQN; else goto cQO; cQN: R2 = _sQ9::P64; R1 = Main.unDataStruct_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cQO: I64[Sp - 8] = block_cQJ_info; R1 = _sQ9::P64; Sp = Sp - 8; if (R1 & 7 != 0) goto cQJ; else goto cQK; cQK: call (I64[R1])(R1) returns to cQJ, args: 8, res: 8, upd: 8; cQJ: _sQa::P64 = R1; _sQb::P64 = P64[_sQa::P64 + 7]; R1 = _sQb::P64 & (-8); Sp = Sp + 8; call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } section ""data" . $tc'MyNewtypeConstr1_rGD_closure" { $tc'MyNewtypeConstr1_rGD_closure: const GHC.Types.TrNameS_static_info; const cRI_str; } section ""data" . Main.$tc'MyNewtypeConstr_closure" { Main.$tc'MyNewtypeConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyNewtypeConstr1_rGD_closure+1; const 10344856529254187725; const 4384341159368653246; const 3; } section ""data" . $tc'MyDataConstr1_rGF_closure" { $tc'MyDataConstr1_rGF_closure: const GHC.Types.TrNameS_static_info; const cRU_str; } section ""data" . Main.$tc'MyDataConstr_closure" { Main.$tc'MyDataConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyDataConstr1_rGF_closure+1; const 12971553621823397951; const 6686958652479025466; const 3; } section ""data" . Main.MyDataConstr_closure" { Main.MyDataConstr_closure: const Main.MyDataConstr_info; } Main.MyDataConstr_entry() // [R2] { [(cSE, Main.MyDataConstr_info: const 4294967301; const 0; const 15;)] } {offset cSE: _B1::P64 = R2; goto cSG; cSG: Hp = Hp + 16; if (Hp > I64[BaseReg + 856]) goto cSI; else goto cSH; cSI: I64[BaseReg + 904] = 16; goto cSF; cSF: R2 = _B1::P64; R1 = Main.MyDataConstr_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cSH: I64[Hp - 8] = Main.MyDataConstr_con_info; P64[Hp] = _B1::P64; _cSD::P64 = Hp - 7; R1 = _cSD::P64; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_con_entry() // [] { [(cSN, Main.MyDataConstr_con_info: const iSP_str-Main.MyDataConstr_con_info; const 1; const 2;)] } {offset cSN: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_static_entry() // [] { [(cSO, Main.MyDataConstr_static_info: const iSQ_str-Main.MyDataConstr_static_info; const 1; const 7;)] } {offset cSO: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } -- LLVM ------------------------------------------------------------------------ %Main_zdtczqMyNewtypeConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyNewtypeConstr_closure$def = internal global %Main_zdtczqMyNewtypeConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGD_closure_struct* @rGD_closure$def to i64),i64 1), i64 -8101887544455363891, i64 4384341159368653246, i64 3}> @Main_zdtczqMyNewtypeConstr_closure = alias i8* bitcast (%Main_zdtczqMyNewtypeConstr_closure_struct* @Main_zdtczqMyNewtypeConstr_closure$def to i8*) %Main_zdtcMyNewtypeStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyNewtypeStruct_closure$def = internal global %Main_zdtcMyNewtypeStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGE_closure_struct* @rGE_closure$def to i64),i64 1), i64 2735651172251469986, i64 2399541496478989519, i64 3}> @Main_zdtcMyNewtypeStruct_closure = alias i8* bitcast (%Main_zdtcMyNewtypeStruct_closure_struct* @Main_zdtcMyNewtypeStruct_closure$def to i8*) %Main_zdtczqMyDataConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyDataConstr_closure$def = internal global %Main_zdtczqMyDataConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGF_closure_struct* @rGF_closure$def to i64),i64 1), i64 -5475190451886153665, i64 6686958652479025466, i64 3}> @Main_zdtczqMyDataConstr_closure = alias i8* bitcast (%Main_zdtczqMyDataConstr_closure_struct* @Main_zdtczqMyDataConstr_closure$def to i8*) %Main_zdtcMyDataStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyDataStruct_closure$def = internal global %Main_zdtcMyDataStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGG_closure_struct* @rGG_closure$def to i64),i64 1), i64 5826051442705447975, i64 -4331072423017222539, i64 3}> @Main_zdtcMyDataStruct_closure = alias i8* bitcast (%Main_zdtcMyDataStruct_closure_struct* @Main_zdtcMyDataStruct_closure$def to i8*) %Main_MyDataConstr_closure_struct = type <{i64}> @Main_MyDataConstr_closure$def = internal global %Main_MyDataConstr_closure_struct<{i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i64)}> @Main_MyDataConstr_closure = alias i8* bitcast (%Main_MyDataConstr_closure_struct* @Main_MyDataConstr_closure$def to i8*) @Main_MyDataConstr_info = internal alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i8*) define internal ghccc void @Main_MyDataConstr_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 4294967301, i64 0, i64 15}> { cW0: ... ret void } @Main_MyDataConstr_con_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i8*) define ghccc void @Main_MyDataConstr_con_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWK_str_struct* @iWK_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i64)),i64 0), i64 1, i64 2}> { ... } @Main_MyDataConstr_static_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i8*) define ghccc void @Main_MyDataConstr_static_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWL_str_struct* @iWL_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i64)),i64 0), i64 1, i64 7}> { ... }
Main_zdtcMyNewtypeStruct_closure_struct <{i64 ptrtoint (i8 * @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (% Main_zdtrModule_closure_struct * @ Main_zdtrModule_closure $ def to i64), i64 -- CORE ------------------------------------------------------------------------ unNewtypeStruct1_rG2 :: MyNewtypeStruct -> MyNewtypeStruct unNewtypeStruct1_rG2 = \ (ds_dGl :: MyNewtypeStruct) -> ds_dGl unNewtypeStruct :: MyNewtypeStruct -> Int unNewtypeStruct = unNewtypeStruct1_rG2 `cast` (<MyNewtypeStruct>_R -> N:MyNewtypeStruct[0] :: ((MyNewtypeStruct -> MyNewtypeStruct) :: *) ~R# ((MyNewtypeStruct -> Int) :: *)) unDataStruct :: MyDataStruct -> Int unDataStruct = \ (ds_dGj :: MyDataStruct) -> case ds_dGj of _ [Occ=Dead] { MyDataConstr ds1_dGk -> ds1_dGk } ntToD :: MyNewtypeStruct -> MyDataStruct ntToD = MyDataConstr `cast` (Sym N:MyNewtypeStruct[0] -> <MyDataStruct>_R :: ((Int -> MyDataStruct) :: *) ~R# ((MyNewtypeStruct -> MyDataStruct) :: *)) dToNt :: MyDataStruct -> MyNewtypeStruct dToNt = \ (x_awb :: MyDataStruct) -> case x_awb of _ [Occ=Dead] { MyDataConstr y_awc -> y_awc `cast` (Sym N:MyNewtypeStruct[0] :: (Int :: *) ~R# (MyNewtypeStruct :: *)) -- ... $tc'MyNewtypeConstr1_rGD :: TrName $tc'MyNewtypeConstr1_rGD = TrNameS "'MyNewtypeConstr"# $tc'MyDataConstr1_rGF :: TrName $tc'MyDataConstr1_rGF = TrNameS "'MyDataConstr"# -- .. $tcMyNewtypeStruct1_rGE :: TrName $tcMyNewtypeStruct1_rGE = TrNameS "MyNewtypeStruct"# $tcMyDataStruct1_rGG :: TrName $tcMyDataStruct1_rGG = TrNameS "MyDataStruct"# -- ... -- STG ------------------------------------------------------------------------- unNewtypeStruct1_rG2 :: Main.MyNewtypeStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = sat-only \r srt:SRT:[] [ds_sQ7] ds_sQ7; Main.unNewtypeStruct :: Main.MyNewtypeStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] unNewtypeStruct1_rG2 eta_B1; Main.unDataStruct :: Main.MyDataStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [ds_sQ8] case ds_sQ8 of _ [Occ=Dead] { Main.MyDataConstr ds1_sQa [Occ=Once] -> ds1_sQa; }; Main.ntToD :: Main.MyNewtypeStruct -> Main.MyDataStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; Main.dToNt :: Main.MyDataStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [x_sQb] case x_sQb of _ [Occ=Dead] { Main.MyDataConstr y_sQd [Occ=Once] -> y_sQd; }; -- ... constructors seem to be defined exactly the same way for both types ... -- There is one more definition in the STG dump Main.MyDataConstr :: GHC.Types.Int -> Main.MyDataStruct [GblId[DataCon], Arity=1, Caf=NoCafRefs, Str=DmdType <L,U>m, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; -- C-- ------------------------------------------------------------------------- unNewtypeStruct1_rG2_entry() // [R2] { [(cQj, unNewtypeStruct1_rG2_info: const 4294967301; const 0; const 15;)] } {offset cQj: _sQ8::P64 = R2; goto cQl; cQl: R1 = _sQ8::P64 & (-8); call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } Main.unNewtypeStruct_entry() // [R2] { [(cQv, Main.unNewtypeStruct_info: const 4294967301; const 0; const 15;)] } {offset cQv: _B1::P64 = R2; goto cQx; cQx: R2 = _B1::P64; call unNewtypeStruct1_rG2_info(R2) args: 8, res: 0, upd: 8; } } Main.unDataStruct_entry() // [R2] { [(cQJ, block_cQJ_info: const 0; const 32;), (cQM, Main.unDataStruct_info: const 4294967301; const 0; const 15;)] } {offset cQM: _sQ9::P64 = R2; if ((Sp + -8) < SpLim) goto cQN; else goto cQO; cQN: R2 = _sQ9::P64; R1 = Main.unDataStruct_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cQO: I64[Sp - 8] = block_cQJ_info; R1 = _sQ9::P64; Sp = Sp - 8; if (R1 & 7 != 0) goto cQJ; else goto cQK; cQK: call (I64[R1])(R1) returns to cQJ, args: 8, res: 8, upd: 8; cQJ: _sQa::P64 = R1; _sQb::P64 = P64[_sQa::P64 + 7]; R1 = _sQb::P64 & (-8); Sp = Sp + 8; call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } section ""data" . $tc'MyNewtypeConstr1_rGD_closure" { $tc'MyNewtypeConstr1_rGD_closure: const GHC.Types.TrNameS_static_info; const cRI_str; } section ""data" . Main.$tc'MyNewtypeConstr_closure" { Main.$tc'MyNewtypeConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyNewtypeConstr1_rGD_closure+1; const 10344856529254187725; const 4384341159368653246; const 3; } section ""data" . $tc'MyDataConstr1_rGF_closure" { $tc'MyDataConstr1_rGF_closure: const GHC.Types.TrNameS_static_info; const cRU_str; } section ""data" . Main.$tc'MyDataConstr_closure" { Main.$tc'MyDataConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyDataConstr1_rGF_closure+1; const 12971553621823397951; const 6686958652479025466; const 3; } section ""data" . Main.MyDataConstr_closure" { Main.MyDataConstr_closure: const Main.MyDataConstr_info; } Main.MyDataConstr_entry() // [R2] { [(cSE, Main.MyDataConstr_info: const 4294967301; const 0; const 15;)] } {offset cSE: _B1::P64 = R2; goto cSG; cSG: Hp = Hp + 16; if (Hp > I64[BaseReg + 856]) goto cSI; else goto cSH; cSI: I64[BaseReg + 904] = 16; goto cSF; cSF: R2 = _B1::P64; R1 = Main.MyDataConstr_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cSH: I64[Hp - 8] = Main.MyDataConstr_con_info; P64[Hp] = _B1::P64; _cSD::P64 = Hp - 7; R1 = _cSD::P64; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_con_entry() // [] { [(cSN, Main.MyDataConstr_con_info: const iSP_str-Main.MyDataConstr_con_info; const 1; const 2;)] } {offset cSN: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_static_entry() // [] { [(cSO, Main.MyDataConstr_static_info: const iSQ_str-Main.MyDataConstr_static_info; const 1; const 7;)] } {offset cSO: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } -- LLVM ------------------------------------------------------------------------ %Main_zdtczqMyNewtypeConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyNewtypeConstr_closure$def = internal global %Main_zdtczqMyNewtypeConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGD_closure_struct* @rGD_closure$def to i64),i64 1), i64 -8101887544455363891, i64 4384341159368653246, i64 3}> @Main_zdtczqMyNewtypeConstr_closure = alias i8* bitcast (%Main_zdtczqMyNewtypeConstr_closure_struct* @Main_zdtczqMyNewtypeConstr_closure$def to i8*) %Main_zdtcMyNewtypeStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyNewtypeStruct_closure$def = internal global %Main_zdtcMyNewtypeStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGE_closure_struct* @rGE_closure$def to i64),i64 1), i64 2735651172251469986, i64 2399541496478989519, i64 3}> @Main_zdtcMyNewtypeStruct_closure = alias i8* bitcast (%Main_zdtcMyNewtypeStruct_closure_struct* @Main_zdtcMyNewtypeStruct_closure$def to i8*) %Main_zdtczqMyDataConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyDataConstr_closure$def = internal global %Main_zdtczqMyDataConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGF_closure_struct* @rGF_closure$def to i64),i64 1), i64 -5475190451886153665, i64 6686958652479025466, i64 3}> @Main_zdtczqMyDataConstr_closure = alias i8* bitcast (%Main_zdtczqMyDataConstr_closure_struct* @Main_zdtczqMyDataConstr_closure$def to i8*) %Main_zdtcMyDataStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyDataStruct_closure$def = internal global %Main_zdtcMyDataStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGG_closure_struct* @rGG_closure$def to i64),i64 1), i64 5826051442705447975, i64 -4331072423017222539, i64 3}> @Main_zdtcMyDataStruct_closure = alias i8* bitcast (%Main_zdtcMyDataStruct_closure_struct* @Main_zdtcMyDataStruct_closure$def to i8*) %Main_MyDataConstr_closure_struct = type <{i64}> @Main_MyDataConstr_closure$def = internal global %Main_MyDataConstr_closure_struct<{i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i64)}> @Main_MyDataConstr_closure = alias i8* bitcast (%Main_MyDataConstr_closure_struct* @Main_MyDataConstr_closure$def to i8*) @Main_MyDataConstr_info = internal alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i8*) define internal ghccc void @Main_MyDataConstr_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 4294967301, i64 0, i64 15}> { cW0: ... ret void } @Main_MyDataConstr_con_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i8*) define ghccc void @Main_MyDataConstr_con_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWK_str_struct* @iWK_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i64)),i64 0), i64 1, i64 2}> { ... } @Main_MyDataConstr_static_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i8*) define ghccc void @Main_MyDataConstr_static_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWL_str_struct* @iWL_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i64)),i64 0), i64 1, i64 7}> { ... }
% -- CORE ------------------------------------------------------------------------ unNewtypeStruct1_rG2 :: MyNewtypeStruct -> MyNewtypeStruct unNewtypeStruct1_rG2 = \ (ds_dGl :: MyNewtypeStruct) -> ds_dGl unNewtypeStruct :: MyNewtypeStruct -> Int unNewtypeStruct = unNewtypeStruct1_rG2 `cast` (<MyNewtypeStruct>_R -> N:MyNewtypeStruct[0] :: ((MyNewtypeStruct -> MyNewtypeStruct) :: *) ~R# ((MyNewtypeStruct -> Int) :: *)) unDataStruct :: MyDataStruct -> Int unDataStruct = \ (ds_dGj :: MyDataStruct) -> case ds_dGj of _ [Occ=Dead] { MyDataConstr ds1_dGk -> ds1_dGk } ntToD :: MyNewtypeStruct -> MyDataStruct ntToD = MyDataConstr `cast` (Sym N:MyNewtypeStruct[0] -> <MyDataStruct>_R :: ((Int -> MyDataStruct) :: *) ~R# ((MyNewtypeStruct -> MyDataStruct) :: *)) dToNt :: MyDataStruct -> MyNewtypeStruct dToNt = \ (x_awb :: MyDataStruct) -> case x_awb of _ [Occ=Dead] { MyDataConstr y_awc -> y_awc `cast` (Sym N:MyNewtypeStruct[0] :: (Int :: *) ~R# (MyNewtypeStruct :: *)) -- ... $tc'MyNewtypeConstr1_rGD :: TrName $tc'MyNewtypeConstr1_rGD = TrNameS "'MyNewtypeConstr"# $tc'MyDataConstr1_rGF :: TrName $tc'MyDataConstr1_rGF = TrNameS "'MyDataConstr"# -- .. $tcMyNewtypeStruct1_rGE :: TrName $tcMyNewtypeStruct1_rGE = TrNameS "MyNewtypeStruct"# $tcMyDataStruct1_rGG :: TrName $tcMyDataStruct1_rGG = TrNameS "MyDataStruct"# -- ... -- STG ------------------------------------------------------------------------- unNewtypeStruct1_rG2 :: Main.MyNewtypeStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = sat-only \r srt:SRT:[] [ds_sQ7] ds_sQ7; Main.unNewtypeStruct :: Main.MyNewtypeStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] unNewtypeStruct1_rG2 eta_B1; Main.unDataStruct :: Main.MyDataStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [ds_sQ8] case ds_sQ8 of _ [Occ=Dead] { Main.MyDataConstr ds1_sQa [Occ=Once] -> ds1_sQa; }; Main.ntToD :: Main.MyNewtypeStruct -> Main.MyDataStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; Main.dToNt :: Main.MyDataStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [x_sQb] case x_sQb of _ [Occ=Dead] { Main.MyDataConstr y_sQd [Occ=Once] -> y_sQd; }; -- ... constructors seem to be defined exactly the same way for both types ... -- There is one more definition in the STG dump Main.MyDataConstr :: GHC.Types.Int -> Main.MyDataStruct [GblId[DataCon], Arity=1, Caf=NoCafRefs, Str=DmdType <L,U>m, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; -- C-- ------------------------------------------------------------------------- unNewtypeStruct1_rG2_entry() // [R2] { [(cQj, unNewtypeStruct1_rG2_info: const 4294967301; const 0; const 15;)] } {offset cQj: _sQ8::P64 = R2; goto cQl; cQl: R1 = _sQ8::P64 & (-8); call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } Main.unNewtypeStruct_entry() // [R2] { [(cQv, Main.unNewtypeStruct_info: const 4294967301; const 0; const 15;)] } {offset cQv: _B1::P64 = R2; goto cQx; cQx: R2 = _B1::P64; call unNewtypeStruct1_rG2_info(R2) args: 8, res: 0, upd: 8; } } Main.unDataStruct_entry() // [R2] { [(cQJ, block_cQJ_info: const 0; const 32;), (cQM, Main.unDataStruct_info: const 4294967301; const 0; const 15;)] } {offset cQM: _sQ9::P64 = R2; if ((Sp + -8) < SpLim) goto cQN; else goto cQO; cQN: R2 = _sQ9::P64; R1 = Main.unDataStruct_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cQO: I64[Sp - 8] = block_cQJ_info; R1 = _sQ9::P64; Sp = Sp - 8; if (R1 & 7 != 0) goto cQJ; else goto cQK; cQK: call (I64[R1])(R1) returns to cQJ, args: 8, res: 8, upd: 8; cQJ: _sQa::P64 = R1; _sQb::P64 = P64[_sQa::P64 + 7]; R1 = _sQb::P64 & (-8); Sp = Sp + 8; call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } section ""data" . $tc'MyNewtypeConstr1_rGD_closure" { $tc'MyNewtypeConstr1_rGD_closure: const GHC.Types.TrNameS_static_info; const cRI_str; } section ""data" . Main.$tc'MyNewtypeConstr_closure" { Main.$tc'MyNewtypeConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyNewtypeConstr1_rGD_closure+1; const 10344856529254187725; const 4384341159368653246; const 3; } section ""data" . $tc'MyDataConstr1_rGF_closure" { $tc'MyDataConstr1_rGF_closure: const GHC.Types.TrNameS_static_info; const cRU_str; } section ""data" . Main.$tc'MyDataConstr_closure" { Main.$tc'MyDataConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyDataConstr1_rGF_closure+1; const 12971553621823397951; const 6686958652479025466; const 3; } section ""data" . Main.MyDataConstr_closure" { Main.MyDataConstr_closure: const Main.MyDataConstr_info; } Main.MyDataConstr_entry() // [R2] { [(cSE, Main.MyDataConstr_info: const 4294967301; const 0; const 15;)] } {offset cSE: _B1::P64 = R2; goto cSG; cSG: Hp = Hp + 16; if (Hp > I64[BaseReg + 856]) goto cSI; else goto cSH; cSI: I64[BaseReg + 904] = 16; goto cSF; cSF: R2 = _B1::P64; R1 = Main.MyDataConstr_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cSH: I64[Hp - 8] = Main.MyDataConstr_con_info; P64[Hp] = _B1::P64; _cSD::P64 = Hp - 7; R1 = _cSD::P64; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_con_entry() // [] { [(cSN, Main.MyDataConstr_con_info: const iSP_str-Main.MyDataConstr_con_info; const 1; const 2;)] } {offset cSN: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_static_entry() // [] { [(cSO, Main.MyDataConstr_static_info: const iSQ_str-Main.MyDataConstr_static_info; const 1; const 7;)] } {offset cSO: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } -- LLVM ------------------------------------------------------------------------ %Main_zdtczqMyNewtypeConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyNewtypeConstr_closure$def = internal global %Main_zdtczqMyNewtypeConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGD_closure_struct* @rGD_closure$def to i64),i64 1), i64 -8101887544455363891, i64 4384341159368653246, i64 3}> @Main_zdtczqMyNewtypeConstr_closure = alias i8* bitcast (%Main_zdtczqMyNewtypeConstr_closure_struct* @Main_zdtczqMyNewtypeConstr_closure$def to i8*) %Main_zdtcMyNewtypeStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyNewtypeStruct_closure$def = internal global %Main_zdtcMyNewtypeStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGE_closure_struct* @rGE_closure$def to i64),i64 1), i64 2735651172251469986, i64 2399541496478989519, i64 3}> @Main_zdtcMyNewtypeStruct_closure = alias i8* bitcast (%Main_zdtcMyNewtypeStruct_closure_struct* @Main_zdtcMyNewtypeStruct_closure$def to i8*) %Main_zdtczqMyDataConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyDataConstr_closure$def = internal global %Main_zdtczqMyDataConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGF_closure_struct* @rGF_closure$def to i64),i64 1), i64 -5475190451886153665, i64 6686958652479025466, i64 3}> @Main_zdtczqMyDataConstr_closure = alias i8* bitcast (%Main_zdtczqMyDataConstr_closure_struct* @Main_zdtczqMyDataConstr_closure$def to i8*) %Main_zdtcMyDataStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyDataStruct_closure$def = internal global %Main_zdtcMyDataStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGG_closure_struct* @rGG_closure$def to i64),i64 1), i64 5826051442705447975, i64 -4331072423017222539, i64 3}> @Main_zdtcMyDataStruct_closure = alias i8* bitcast (%Main_zdtcMyDataStruct_closure_struct* @Main_zdtcMyDataStruct_closure$def to i8*) %Main_MyDataConstr_closure_struct = type <{i64}> @Main_MyDataConstr_closure$def = internal global %Main_MyDataConstr_closure_struct<{i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i64)}> @Main_MyDataConstr_closure = alias i8* bitcast (%Main_MyDataConstr_closure_struct* @Main_MyDataConstr_closure$def to i8*) @Main_MyDataConstr_info = internal alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i8*) define internal ghccc void @Main_MyDataConstr_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 4294967301, i64 0, i64 15}> { cW0: ... ret void } @Main_MyDataConstr_con_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i8*) define ghccc void @Main_MyDataConstr_con_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWK_str_struct* @iWK_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i64)),i64 0), i64 1, i64 2}> { ... } @Main_MyDataConstr_static_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i8*) define ghccc void @Main_MyDataConstr_static_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWL_str_struct* @iWL_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i64)),i64 0), i64 1, i64 7}> { ... }
Main_zdtczqMyDataConstr_closure_struct <{i64 ptrtoint (i8 * @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (% Main_zdtrModule_closure_struct * @ Main_zdtrModule_closure $ def to i64), i64 -- CORE ------------------------------------------------------------------------ unNewtypeStruct1_rG2 :: MyNewtypeStruct -> MyNewtypeStruct unNewtypeStruct1_rG2 = \ (ds_dGl :: MyNewtypeStruct) -> ds_dGl unNewtypeStruct :: MyNewtypeStruct -> Int unNewtypeStruct = unNewtypeStruct1_rG2 `cast` (<MyNewtypeStruct>_R -> N:MyNewtypeStruct[0] :: ((MyNewtypeStruct -> MyNewtypeStruct) :: *) ~R# ((MyNewtypeStruct -> Int) :: *)) unDataStruct :: MyDataStruct -> Int unDataStruct = \ (ds_dGj :: MyDataStruct) -> case ds_dGj of _ [Occ=Dead] { MyDataConstr ds1_dGk -> ds1_dGk } ntToD :: MyNewtypeStruct -> MyDataStruct ntToD = MyDataConstr `cast` (Sym N:MyNewtypeStruct[0] -> <MyDataStruct>_R :: ((Int -> MyDataStruct) :: *) ~R# ((MyNewtypeStruct -> MyDataStruct) :: *)) dToNt :: MyDataStruct -> MyNewtypeStruct dToNt = \ (x_awb :: MyDataStruct) -> case x_awb of _ [Occ=Dead] { MyDataConstr y_awc -> y_awc `cast` (Sym N:MyNewtypeStruct[0] :: (Int :: *) ~R# (MyNewtypeStruct :: *)) -- ... $tc'MyNewtypeConstr1_rGD :: TrName $tc'MyNewtypeConstr1_rGD = TrNameS "'MyNewtypeConstr"# $tc'MyDataConstr1_rGF :: TrName $tc'MyDataConstr1_rGF = TrNameS "'MyDataConstr"# -- .. $tcMyNewtypeStruct1_rGE :: TrName $tcMyNewtypeStruct1_rGE = TrNameS "MyNewtypeStruct"# $tcMyDataStruct1_rGG :: TrName $tcMyDataStruct1_rGG = TrNameS "MyDataStruct"# -- ... -- STG ------------------------------------------------------------------------- unNewtypeStruct1_rG2 :: Main.MyNewtypeStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = sat-only \r srt:SRT:[] [ds_sQ7] ds_sQ7; Main.unNewtypeStruct :: Main.MyNewtypeStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] unNewtypeStruct1_rG2 eta_B1; Main.unDataStruct :: Main.MyDataStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [ds_sQ8] case ds_sQ8 of _ [Occ=Dead] { Main.MyDataConstr ds1_sQa [Occ=Once] -> ds1_sQa; }; Main.ntToD :: Main.MyNewtypeStruct -> Main.MyDataStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; Main.dToNt :: Main.MyDataStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [x_sQb] case x_sQb of _ [Occ=Dead] { Main.MyDataConstr y_sQd [Occ=Once] -> y_sQd; }; -- ... constructors seem to be defined exactly the same way for both types ... -- There is one more definition in the STG dump Main.MyDataConstr :: GHC.Types.Int -> Main.MyDataStruct [GblId[DataCon], Arity=1, Caf=NoCafRefs, Str=DmdType <L,U>m, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; -- C-- ------------------------------------------------------------------------- unNewtypeStruct1_rG2_entry() // [R2] { [(cQj, unNewtypeStruct1_rG2_info: const 4294967301; const 0; const 15;)] } {offset cQj: _sQ8::P64 = R2; goto cQl; cQl: R1 = _sQ8::P64 & (-8); call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } Main.unNewtypeStruct_entry() // [R2] { [(cQv, Main.unNewtypeStruct_info: const 4294967301; const 0; const 15;)] } {offset cQv: _B1::P64 = R2; goto cQx; cQx: R2 = _B1::P64; call unNewtypeStruct1_rG2_info(R2) args: 8, res: 0, upd: 8; } } Main.unDataStruct_entry() // [R2] { [(cQJ, block_cQJ_info: const 0; const 32;), (cQM, Main.unDataStruct_info: const 4294967301; const 0; const 15;)] } {offset cQM: _sQ9::P64 = R2; if ((Sp + -8) < SpLim) goto cQN; else goto cQO; cQN: R2 = _sQ9::P64; R1 = Main.unDataStruct_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cQO: I64[Sp - 8] = block_cQJ_info; R1 = _sQ9::P64; Sp = Sp - 8; if (R1 & 7 != 0) goto cQJ; else goto cQK; cQK: call (I64[R1])(R1) returns to cQJ, args: 8, res: 8, upd: 8; cQJ: _sQa::P64 = R1; _sQb::P64 = P64[_sQa::P64 + 7]; R1 = _sQb::P64 & (-8); Sp = Sp + 8; call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } section ""data" . $tc'MyNewtypeConstr1_rGD_closure" { $tc'MyNewtypeConstr1_rGD_closure: const GHC.Types.TrNameS_static_info; const cRI_str; } section ""data" . Main.$tc'MyNewtypeConstr_closure" { Main.$tc'MyNewtypeConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyNewtypeConstr1_rGD_closure+1; const 10344856529254187725; const 4384341159368653246; const 3; } section ""data" . $tc'MyDataConstr1_rGF_closure" { $tc'MyDataConstr1_rGF_closure: const GHC.Types.TrNameS_static_info; const cRU_str; } section ""data" . Main.$tc'MyDataConstr_closure" { Main.$tc'MyDataConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyDataConstr1_rGF_closure+1; const 12971553621823397951; const 6686958652479025466; const 3; } section ""data" . Main.MyDataConstr_closure" { Main.MyDataConstr_closure: const Main.MyDataConstr_info; } Main.MyDataConstr_entry() // [R2] { [(cSE, Main.MyDataConstr_info: const 4294967301; const 0; const 15;)] } {offset cSE: _B1::P64 = R2; goto cSG; cSG: Hp = Hp + 16; if (Hp > I64[BaseReg + 856]) goto cSI; else goto cSH; cSI: I64[BaseReg + 904] = 16; goto cSF; cSF: R2 = _B1::P64; R1 = Main.MyDataConstr_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cSH: I64[Hp - 8] = Main.MyDataConstr_con_info; P64[Hp] = _B1::P64; _cSD::P64 = Hp - 7; R1 = _cSD::P64; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_con_entry() // [] { [(cSN, Main.MyDataConstr_con_info: const iSP_str-Main.MyDataConstr_con_info; const 1; const 2;)] } {offset cSN: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_static_entry() // [] { [(cSO, Main.MyDataConstr_static_info: const iSQ_str-Main.MyDataConstr_static_info; const 1; const 7;)] } {offset cSO: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } -- LLVM ------------------------------------------------------------------------ %Main_zdtczqMyNewtypeConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyNewtypeConstr_closure$def = internal global %Main_zdtczqMyNewtypeConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGD_closure_struct* @rGD_closure$def to i64),i64 1), i64 -8101887544455363891, i64 4384341159368653246, i64 3}> @Main_zdtczqMyNewtypeConstr_closure = alias i8* bitcast (%Main_zdtczqMyNewtypeConstr_closure_struct* @Main_zdtczqMyNewtypeConstr_closure$def to i8*) %Main_zdtcMyNewtypeStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyNewtypeStruct_closure$def = internal global %Main_zdtcMyNewtypeStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGE_closure_struct* @rGE_closure$def to i64),i64 1), i64 2735651172251469986, i64 2399541496478989519, i64 3}> @Main_zdtcMyNewtypeStruct_closure = alias i8* bitcast (%Main_zdtcMyNewtypeStruct_closure_struct* @Main_zdtcMyNewtypeStruct_closure$def to i8*) %Main_zdtczqMyDataConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyDataConstr_closure$def = internal global %Main_zdtczqMyDataConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGF_closure_struct* @rGF_closure$def to i64),i64 1), i64 -5475190451886153665, i64 6686958652479025466, i64 3}> @Main_zdtczqMyDataConstr_closure = alias i8* bitcast (%Main_zdtczqMyDataConstr_closure_struct* @Main_zdtczqMyDataConstr_closure$def to i8*) %Main_zdtcMyDataStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyDataStruct_closure$def = internal global %Main_zdtcMyDataStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGG_closure_struct* @rGG_closure$def to i64),i64 1), i64 5826051442705447975, i64 -4331072423017222539, i64 3}> @Main_zdtcMyDataStruct_closure = alias i8* bitcast (%Main_zdtcMyDataStruct_closure_struct* @Main_zdtcMyDataStruct_closure$def to i8*) %Main_MyDataConstr_closure_struct = type <{i64}> @Main_MyDataConstr_closure$def = internal global %Main_MyDataConstr_closure_struct<{i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i64)}> @Main_MyDataConstr_closure = alias i8* bitcast (%Main_MyDataConstr_closure_struct* @Main_MyDataConstr_closure$def to i8*) @Main_MyDataConstr_info = internal alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i8*) define internal ghccc void @Main_MyDataConstr_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 4294967301, i64 0, i64 15}> { cW0: ... ret void } @Main_MyDataConstr_con_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i8*) define ghccc void @Main_MyDataConstr_con_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWK_str_struct* @iWK_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i64)),i64 0), i64 1, i64 2}> { ... } @Main_MyDataConstr_static_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i8*) define ghccc void @Main_MyDataConstr_static_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWL_str_struct* @iWL_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i64)),i64 0), i64 1, i64 7}> { ... }
% -- CORE ------------------------------------------------------------------------ unNewtypeStruct1_rG2 :: MyNewtypeStruct -> MyNewtypeStruct unNewtypeStruct1_rG2 = \ (ds_dGl :: MyNewtypeStruct) -> ds_dGl unNewtypeStruct :: MyNewtypeStruct -> Int unNewtypeStruct = unNewtypeStruct1_rG2 `cast` (<MyNewtypeStruct>_R -> N:MyNewtypeStruct[0] :: ((MyNewtypeStruct -> MyNewtypeStruct) :: *) ~R# ((MyNewtypeStruct -> Int) :: *)) unDataStruct :: MyDataStruct -> Int unDataStruct = \ (ds_dGj :: MyDataStruct) -> case ds_dGj of _ [Occ=Dead] { MyDataConstr ds1_dGk -> ds1_dGk } ntToD :: MyNewtypeStruct -> MyDataStruct ntToD = MyDataConstr `cast` (Sym N:MyNewtypeStruct[0] -> <MyDataStruct>_R :: ((Int -> MyDataStruct) :: *) ~R# ((MyNewtypeStruct -> MyDataStruct) :: *)) dToNt :: MyDataStruct -> MyNewtypeStruct dToNt = \ (x_awb :: MyDataStruct) -> case x_awb of _ [Occ=Dead] { MyDataConstr y_awc -> y_awc `cast` (Sym N:MyNewtypeStruct[0] :: (Int :: *) ~R# (MyNewtypeStruct :: *)) -- ... $tc'MyNewtypeConstr1_rGD :: TrName $tc'MyNewtypeConstr1_rGD = TrNameS "'MyNewtypeConstr"# $tc'MyDataConstr1_rGF :: TrName $tc'MyDataConstr1_rGF = TrNameS "'MyDataConstr"# -- .. $tcMyNewtypeStruct1_rGE :: TrName $tcMyNewtypeStruct1_rGE = TrNameS "MyNewtypeStruct"# $tcMyDataStruct1_rGG :: TrName $tcMyDataStruct1_rGG = TrNameS "MyDataStruct"# -- ... -- STG ------------------------------------------------------------------------- unNewtypeStruct1_rG2 :: Main.MyNewtypeStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = sat-only \r srt:SRT:[] [ds_sQ7] ds_sQ7; Main.unNewtypeStruct :: Main.MyNewtypeStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] unNewtypeStruct1_rG2 eta_B1; Main.unDataStruct :: Main.MyDataStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [ds_sQ8] case ds_sQ8 of _ [Occ=Dead] { Main.MyDataConstr ds1_sQa [Occ=Once] -> ds1_sQa; }; Main.ntToD :: Main.MyNewtypeStruct -> Main.MyDataStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; Main.dToNt :: Main.MyDataStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [x_sQb] case x_sQb of _ [Occ=Dead] { Main.MyDataConstr y_sQd [Occ=Once] -> y_sQd; }; -- ... constructors seem to be defined exactly the same way for both types ... -- There is one more definition in the STG dump Main.MyDataConstr :: GHC.Types.Int -> Main.MyDataStruct [GblId[DataCon], Arity=1, Caf=NoCafRefs, Str=DmdType <L,U>m, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; -- C-- ------------------------------------------------------------------------- unNewtypeStruct1_rG2_entry() // [R2] { [(cQj, unNewtypeStruct1_rG2_info: const 4294967301; const 0; const 15;)] } {offset cQj: _sQ8::P64 = R2; goto cQl; cQl: R1 = _sQ8::P64 & (-8); call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } Main.unNewtypeStruct_entry() // [R2] { [(cQv, Main.unNewtypeStruct_info: const 4294967301; const 0; const 15;)] } {offset cQv: _B1::P64 = R2; goto cQx; cQx: R2 = _B1::P64; call unNewtypeStruct1_rG2_info(R2) args: 8, res: 0, upd: 8; } } Main.unDataStruct_entry() // [R2] { [(cQJ, block_cQJ_info: const 0; const 32;), (cQM, Main.unDataStruct_info: const 4294967301; const 0; const 15;)] } {offset cQM: _sQ9::P64 = R2; if ((Sp + -8) < SpLim) goto cQN; else goto cQO; cQN: R2 = _sQ9::P64; R1 = Main.unDataStruct_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cQO: I64[Sp - 8] = block_cQJ_info; R1 = _sQ9::P64; Sp = Sp - 8; if (R1 & 7 != 0) goto cQJ; else goto cQK; cQK: call (I64[R1])(R1) returns to cQJ, args: 8, res: 8, upd: 8; cQJ: _sQa::P64 = R1; _sQb::P64 = P64[_sQa::P64 + 7]; R1 = _sQb::P64 & (-8); Sp = Sp + 8; call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } section ""data" . $tc'MyNewtypeConstr1_rGD_closure" { $tc'MyNewtypeConstr1_rGD_closure: const GHC.Types.TrNameS_static_info; const cRI_str; } section ""data" . Main.$tc'MyNewtypeConstr_closure" { Main.$tc'MyNewtypeConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyNewtypeConstr1_rGD_closure+1; const 10344856529254187725; const 4384341159368653246; const 3; } section ""data" . $tc'MyDataConstr1_rGF_closure" { $tc'MyDataConstr1_rGF_closure: const GHC.Types.TrNameS_static_info; const cRU_str; } section ""data" . Main.$tc'MyDataConstr_closure" { Main.$tc'MyDataConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyDataConstr1_rGF_closure+1; const 12971553621823397951; const 6686958652479025466; const 3; } section ""data" . Main.MyDataConstr_closure" { Main.MyDataConstr_closure: const Main.MyDataConstr_info; } Main.MyDataConstr_entry() // [R2] { [(cSE, Main.MyDataConstr_info: const 4294967301; const 0; const 15;)] } {offset cSE: _B1::P64 = R2; goto cSG; cSG: Hp = Hp + 16; if (Hp > I64[BaseReg + 856]) goto cSI; else goto cSH; cSI: I64[BaseReg + 904] = 16; goto cSF; cSF: R2 = _B1::P64; R1 = Main.MyDataConstr_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cSH: I64[Hp - 8] = Main.MyDataConstr_con_info; P64[Hp] = _B1::P64; _cSD::P64 = Hp - 7; R1 = _cSD::P64; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_con_entry() // [] { [(cSN, Main.MyDataConstr_con_info: const iSP_str-Main.MyDataConstr_con_info; const 1; const 2;)] } {offset cSN: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_static_entry() // [] { [(cSO, Main.MyDataConstr_static_info: const iSQ_str-Main.MyDataConstr_static_info; const 1; const 7;)] } {offset cSO: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } -- LLVM ------------------------------------------------------------------------ %Main_zdtczqMyNewtypeConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyNewtypeConstr_closure$def = internal global %Main_zdtczqMyNewtypeConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGD_closure_struct* @rGD_closure$def to i64),i64 1), i64 -8101887544455363891, i64 4384341159368653246, i64 3}> @Main_zdtczqMyNewtypeConstr_closure = alias i8* bitcast (%Main_zdtczqMyNewtypeConstr_closure_struct* @Main_zdtczqMyNewtypeConstr_closure$def to i8*) %Main_zdtcMyNewtypeStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyNewtypeStruct_closure$def = internal global %Main_zdtcMyNewtypeStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGE_closure_struct* @rGE_closure$def to i64),i64 1), i64 2735651172251469986, i64 2399541496478989519, i64 3}> @Main_zdtcMyNewtypeStruct_closure = alias i8* bitcast (%Main_zdtcMyNewtypeStruct_closure_struct* @Main_zdtcMyNewtypeStruct_closure$def to i8*) %Main_zdtczqMyDataConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyDataConstr_closure$def = internal global %Main_zdtczqMyDataConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGF_closure_struct* @rGF_closure$def to i64),i64 1), i64 -5475190451886153665, i64 6686958652479025466, i64 3}> @Main_zdtczqMyDataConstr_closure = alias i8* bitcast (%Main_zdtczqMyDataConstr_closure_struct* @Main_zdtczqMyDataConstr_closure$def to i8*) %Main_zdtcMyDataStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyDataStruct_closure$def = internal global %Main_zdtcMyDataStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGG_closure_struct* @rGG_closure$def to i64),i64 1), i64 5826051442705447975, i64 -4331072423017222539, i64 3}> @Main_zdtcMyDataStruct_closure = alias i8* bitcast (%Main_zdtcMyDataStruct_closure_struct* @Main_zdtcMyDataStruct_closure$def to i8*) %Main_MyDataConstr_closure_struct = type <{i64}> @Main_MyDataConstr_closure$def = internal global %Main_MyDataConstr_closure_struct<{i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i64)}> @Main_MyDataConstr_closure = alias i8* bitcast (%Main_MyDataConstr_closure_struct* @Main_MyDataConstr_closure$def to i8*) @Main_MyDataConstr_info = internal alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i8*) define internal ghccc void @Main_MyDataConstr_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 4294967301, i64 0, i64 15}> { cW0: ... ret void } @Main_MyDataConstr_con_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i8*) define ghccc void @Main_MyDataConstr_con_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWK_str_struct* @iWK_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i64)),i64 0), i64 1, i64 2}> { ... } @Main_MyDataConstr_static_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i8*) define ghccc void @Main_MyDataConstr_static_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWL_str_struct* @iWL_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i64)),i64 0), i64 1, i64 7}> { ... }
Main_zdtcMyDataStruct_closure_struct <{i64 ptrtoint (i8 * @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (% Main_zdtrModule_closure_struct * @ Main_zdtrModule_closure $ def to i64), i64 -- CORE ------------------------------------------------------------------------ unNewtypeStruct1_rG2 :: MyNewtypeStruct -> MyNewtypeStruct unNewtypeStruct1_rG2 = \ (ds_dGl :: MyNewtypeStruct) -> ds_dGl unNewtypeStruct :: MyNewtypeStruct -> Int unNewtypeStruct = unNewtypeStruct1_rG2 `cast` (<MyNewtypeStruct>_R -> N:MyNewtypeStruct[0] :: ((MyNewtypeStruct -> MyNewtypeStruct) :: *) ~R# ((MyNewtypeStruct -> Int) :: *)) unDataStruct :: MyDataStruct -> Int unDataStruct = \ (ds_dGj :: MyDataStruct) -> case ds_dGj of _ [Occ=Dead] { MyDataConstr ds1_dGk -> ds1_dGk } ntToD :: MyNewtypeStruct -> MyDataStruct ntToD = MyDataConstr `cast` (Sym N:MyNewtypeStruct[0] -> <MyDataStruct>_R :: ((Int -> MyDataStruct) :: *) ~R# ((MyNewtypeStruct -> MyDataStruct) :: *)) dToNt :: MyDataStruct -> MyNewtypeStruct dToNt = \ (x_awb :: MyDataStruct) -> case x_awb of _ [Occ=Dead] { MyDataConstr y_awc -> y_awc `cast` (Sym N:MyNewtypeStruct[0] :: (Int :: *) ~R# (MyNewtypeStruct :: *)) -- ... $tc'MyNewtypeConstr1_rGD :: TrName $tc'MyNewtypeConstr1_rGD = TrNameS "'MyNewtypeConstr"# $tc'MyDataConstr1_rGF :: TrName $tc'MyDataConstr1_rGF = TrNameS "'MyDataConstr"# -- .. $tcMyNewtypeStruct1_rGE :: TrName $tcMyNewtypeStruct1_rGE = TrNameS "MyNewtypeStruct"# $tcMyDataStruct1_rGG :: TrName $tcMyDataStruct1_rGG = TrNameS "MyDataStruct"# -- ... -- STG ------------------------------------------------------------------------- unNewtypeStruct1_rG2 :: Main.MyNewtypeStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = sat-only \r srt:SRT:[] [ds_sQ7] ds_sQ7; Main.unNewtypeStruct :: Main.MyNewtypeStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] unNewtypeStruct1_rG2 eta_B1; Main.unDataStruct :: Main.MyDataStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [ds_sQ8] case ds_sQ8 of _ [Occ=Dead] { Main.MyDataConstr ds1_sQa [Occ=Once] -> ds1_sQa; }; Main.ntToD :: Main.MyNewtypeStruct -> Main.MyDataStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; Main.dToNt :: Main.MyDataStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [x_sQb] case x_sQb of _ [Occ=Dead] { Main.MyDataConstr y_sQd [Occ=Once] -> y_sQd; }; -- ... constructors seem to be defined exactly the same way for both types ... -- There is one more definition in the STG dump Main.MyDataConstr :: GHC.Types.Int -> Main.MyDataStruct [GblId[DataCon], Arity=1, Caf=NoCafRefs, Str=DmdType <L,U>m, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; -- C-- ------------------------------------------------------------------------- unNewtypeStruct1_rG2_entry() // [R2] { [(cQj, unNewtypeStruct1_rG2_info: const 4294967301; const 0; const 15;)] } {offset cQj: _sQ8::P64 = R2; goto cQl; cQl: R1 = _sQ8::P64 & (-8); call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } Main.unNewtypeStruct_entry() // [R2] { [(cQv, Main.unNewtypeStruct_info: const 4294967301; const 0; const 15;)] } {offset cQv: _B1::P64 = R2; goto cQx; cQx: R2 = _B1::P64; call unNewtypeStruct1_rG2_info(R2) args: 8, res: 0, upd: 8; } } Main.unDataStruct_entry() // [R2] { [(cQJ, block_cQJ_info: const 0; const 32;), (cQM, Main.unDataStruct_info: const 4294967301; const 0; const 15;)] } {offset cQM: _sQ9::P64 = R2; if ((Sp + -8) < SpLim) goto cQN; else goto cQO; cQN: R2 = _sQ9::P64; R1 = Main.unDataStruct_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cQO: I64[Sp - 8] = block_cQJ_info; R1 = _sQ9::P64; Sp = Sp - 8; if (R1 & 7 != 0) goto cQJ; else goto cQK; cQK: call (I64[R1])(R1) returns to cQJ, args: 8, res: 8, upd: 8; cQJ: _sQa::P64 = R1; _sQb::P64 = P64[_sQa::P64 + 7]; R1 = _sQb::P64 & (-8); Sp = Sp + 8; call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } section ""data" . $tc'MyNewtypeConstr1_rGD_closure" { $tc'MyNewtypeConstr1_rGD_closure: const GHC.Types.TrNameS_static_info; const cRI_str; } section ""data" . Main.$tc'MyNewtypeConstr_closure" { Main.$tc'MyNewtypeConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyNewtypeConstr1_rGD_closure+1; const 10344856529254187725; const 4384341159368653246; const 3; } section ""data" . $tc'MyDataConstr1_rGF_closure" { $tc'MyDataConstr1_rGF_closure: const GHC.Types.TrNameS_static_info; const cRU_str; } section ""data" . Main.$tc'MyDataConstr_closure" { Main.$tc'MyDataConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyDataConstr1_rGF_closure+1; const 12971553621823397951; const 6686958652479025466; const 3; } section ""data" . Main.MyDataConstr_closure" { Main.MyDataConstr_closure: const Main.MyDataConstr_info; } Main.MyDataConstr_entry() // [R2] { [(cSE, Main.MyDataConstr_info: const 4294967301; const 0; const 15;)] } {offset cSE: _B1::P64 = R2; goto cSG; cSG: Hp = Hp + 16; if (Hp > I64[BaseReg + 856]) goto cSI; else goto cSH; cSI: I64[BaseReg + 904] = 16; goto cSF; cSF: R2 = _B1::P64; R1 = Main.MyDataConstr_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cSH: I64[Hp - 8] = Main.MyDataConstr_con_info; P64[Hp] = _B1::P64; _cSD::P64 = Hp - 7; R1 = _cSD::P64; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_con_entry() // [] { [(cSN, Main.MyDataConstr_con_info: const iSP_str-Main.MyDataConstr_con_info; const 1; const 2;)] } {offset cSN: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_static_entry() // [] { [(cSO, Main.MyDataConstr_static_info: const iSQ_str-Main.MyDataConstr_static_info; const 1; const 7;)] } {offset cSO: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } -- LLVM ------------------------------------------------------------------------ %Main_zdtczqMyNewtypeConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyNewtypeConstr_closure$def = internal global %Main_zdtczqMyNewtypeConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGD_closure_struct* @rGD_closure$def to i64),i64 1), i64 -8101887544455363891, i64 4384341159368653246, i64 3}> @Main_zdtczqMyNewtypeConstr_closure = alias i8* bitcast (%Main_zdtczqMyNewtypeConstr_closure_struct* @Main_zdtczqMyNewtypeConstr_closure$def to i8*) %Main_zdtcMyNewtypeStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyNewtypeStruct_closure$def = internal global %Main_zdtcMyNewtypeStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGE_closure_struct* @rGE_closure$def to i64),i64 1), i64 2735651172251469986, i64 2399541496478989519, i64 3}> @Main_zdtcMyNewtypeStruct_closure = alias i8* bitcast (%Main_zdtcMyNewtypeStruct_closure_struct* @Main_zdtcMyNewtypeStruct_closure$def to i8*) %Main_zdtczqMyDataConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyDataConstr_closure$def = internal global %Main_zdtczqMyDataConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGF_closure_struct* @rGF_closure$def to i64),i64 1), i64 -5475190451886153665, i64 6686958652479025466, i64 3}> @Main_zdtczqMyDataConstr_closure = alias i8* bitcast (%Main_zdtczqMyDataConstr_closure_struct* @Main_zdtczqMyDataConstr_closure$def to i8*) %Main_zdtcMyDataStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyDataStruct_closure$def = internal global %Main_zdtcMyDataStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGG_closure_struct* @rGG_closure$def to i64),i64 1), i64 5826051442705447975, i64 -4331072423017222539, i64 3}> @Main_zdtcMyDataStruct_closure = alias i8* bitcast (%Main_zdtcMyDataStruct_closure_struct* @Main_zdtcMyDataStruct_closure$def to i8*) %Main_MyDataConstr_closure_struct = type <{i64}> @Main_MyDataConstr_closure$def = internal global %Main_MyDataConstr_closure_struct<{i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i64)}> @Main_MyDataConstr_closure = alias i8* bitcast (%Main_MyDataConstr_closure_struct* @Main_MyDataConstr_closure$def to i8*) @Main_MyDataConstr_info = internal alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i8*) define internal ghccc void @Main_MyDataConstr_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 4294967301, i64 0, i64 15}> { cW0: ... ret void } @Main_MyDataConstr_con_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i8*) define ghccc void @Main_MyDataConstr_con_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWK_str_struct* @iWK_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i64)),i64 0), i64 1, i64 2}> { ... } @Main_MyDataConstr_static_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i8*) define ghccc void @Main_MyDataConstr_static_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWL_str_struct* @iWL_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i64)),i64 0), i64 1, i64 7}> { ... }
% -- CORE ------------------------------------------------------------------------ unNewtypeStruct1_rG2 :: MyNewtypeStruct -> MyNewtypeStruct unNewtypeStruct1_rG2 = \ (ds_dGl :: MyNewtypeStruct) -> ds_dGl unNewtypeStruct :: MyNewtypeStruct -> Int unNewtypeStruct = unNewtypeStruct1_rG2 `cast` (<MyNewtypeStruct>_R -> N:MyNewtypeStruct[0] :: ((MyNewtypeStruct -> MyNewtypeStruct) :: *) ~R# ((MyNewtypeStruct -> Int) :: *)) unDataStruct :: MyDataStruct -> Int unDataStruct = \ (ds_dGj :: MyDataStruct) -> case ds_dGj of _ [Occ=Dead] { MyDataConstr ds1_dGk -> ds1_dGk } ntToD :: MyNewtypeStruct -> MyDataStruct ntToD = MyDataConstr `cast` (Sym N:MyNewtypeStruct[0] -> <MyDataStruct>_R :: ((Int -> MyDataStruct) :: *) ~R# ((MyNewtypeStruct -> MyDataStruct) :: *)) dToNt :: MyDataStruct -> MyNewtypeStruct dToNt = \ (x_awb :: MyDataStruct) -> case x_awb of _ [Occ=Dead] { MyDataConstr y_awc -> y_awc `cast` (Sym N:MyNewtypeStruct[0] :: (Int :: *) ~R# (MyNewtypeStruct :: *)) -- ... $tc'MyNewtypeConstr1_rGD :: TrName $tc'MyNewtypeConstr1_rGD = TrNameS "'MyNewtypeConstr"# $tc'MyDataConstr1_rGF :: TrName $tc'MyDataConstr1_rGF = TrNameS "'MyDataConstr"# -- .. $tcMyNewtypeStruct1_rGE :: TrName $tcMyNewtypeStruct1_rGE = TrNameS "MyNewtypeStruct"# $tcMyDataStruct1_rGG :: TrName $tcMyDataStruct1_rGG = TrNameS "MyDataStruct"# -- ... -- STG ------------------------------------------------------------------------- unNewtypeStruct1_rG2 :: Main.MyNewtypeStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = sat-only \r srt:SRT:[] [ds_sQ7] ds_sQ7; Main.unNewtypeStruct :: Main.MyNewtypeStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] unNewtypeStruct1_rG2 eta_B1; Main.unDataStruct :: Main.MyDataStruct -> GHC.Types.Int [GblId[[RecSel]], Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [ds_sQ8] case ds_sQ8 of _ [Occ=Dead] { Main.MyDataConstr ds1_sQa [Occ=Once] -> ds1_sQa; }; Main.ntToD :: Main.MyNewtypeStruct -> Main.MyDataStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; Main.dToNt :: Main.MyDataStruct -> Main.MyNewtypeStruct [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType, Unf=OtherCon []] = \r srt:SRT:[] [x_sQb] case x_sQb of _ [Occ=Dead] { Main.MyDataConstr y_sQd [Occ=Once] -> y_sQd; }; -- ... constructors seem to be defined exactly the same way for both types ... -- There is one more definition in the STG dump Main.MyDataConstr :: GHC.Types.Int -> Main.MyDataStruct [GblId[DataCon], Arity=1, Caf=NoCafRefs, Str=DmdType <L,U>m, Unf=OtherCon []] = \r srt:SRT:[] [eta_B1] Main.MyDataConstr [eta_B1]; -- C-- ------------------------------------------------------------------------- unNewtypeStruct1_rG2_entry() // [R2] { [(cQj, unNewtypeStruct1_rG2_info: const 4294967301; const 0; const 15;)] } {offset cQj: _sQ8::P64 = R2; goto cQl; cQl: R1 = _sQ8::P64 & (-8); call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } Main.unNewtypeStruct_entry() // [R2] { [(cQv, Main.unNewtypeStruct_info: const 4294967301; const 0; const 15;)] } {offset cQv: _B1::P64 = R2; goto cQx; cQx: R2 = _B1::P64; call unNewtypeStruct1_rG2_info(R2) args: 8, res: 0, upd: 8; } } Main.unDataStruct_entry() // [R2] { [(cQJ, block_cQJ_info: const 0; const 32;), (cQM, Main.unDataStruct_info: const 4294967301; const 0; const 15;)] } {offset cQM: _sQ9::P64 = R2; if ((Sp + -8) < SpLim) goto cQN; else goto cQO; cQN: R2 = _sQ9::P64; R1 = Main.unDataStruct_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cQO: I64[Sp - 8] = block_cQJ_info; R1 = _sQ9::P64; Sp = Sp - 8; if (R1 & 7 != 0) goto cQJ; else goto cQK; cQK: call (I64[R1])(R1) returns to cQJ, args: 8, res: 8, upd: 8; cQJ: _sQa::P64 = R1; _sQb::P64 = P64[_sQa::P64 + 7]; R1 = _sQb::P64 & (-8); Sp = Sp + 8; call (I64[R1])(R1) args: 8, res: 0, upd: 8; } } section ""data" . $tc'MyNewtypeConstr1_rGD_closure" { $tc'MyNewtypeConstr1_rGD_closure: const GHC.Types.TrNameS_static_info; const cRI_str; } section ""data" . Main.$tc'MyNewtypeConstr_closure" { Main.$tc'MyNewtypeConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyNewtypeConstr1_rGD_closure+1; const 10344856529254187725; const 4384341159368653246; const 3; } section ""data" . $tc'MyDataConstr1_rGF_closure" { $tc'MyDataConstr1_rGF_closure: const GHC.Types.TrNameS_static_info; const cRU_str; } section ""data" . Main.$tc'MyDataConstr_closure" { Main.$tc'MyDataConstr_closure: const GHC.Types.TyCon_static_info; const Main.$trModule_closure+1; const $tc'MyDataConstr1_rGF_closure+1; const 12971553621823397951; const 6686958652479025466; const 3; } section ""data" . Main.MyDataConstr_closure" { Main.MyDataConstr_closure: const Main.MyDataConstr_info; } Main.MyDataConstr_entry() // [R2] { [(cSE, Main.MyDataConstr_info: const 4294967301; const 0; const 15;)] } {offset cSE: _B1::P64 = R2; goto cSG; cSG: Hp = Hp + 16; if (Hp > I64[BaseReg + 856]) goto cSI; else goto cSH; cSI: I64[BaseReg + 904] = 16; goto cSF; cSF: R2 = _B1::P64; R1 = Main.MyDataConstr_closure; call (I64[BaseReg - 8])(R2, R1) args: 8, res: 0, upd: 8; cSH: I64[Hp - 8] = Main.MyDataConstr_con_info; P64[Hp] = _B1::P64; _cSD::P64 = Hp - 7; R1 = _cSD::P64; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_con_entry() // [] { [(cSN, Main.MyDataConstr_con_info: const iSP_str-Main.MyDataConstr_con_info; const 1; const 2;)] } {offset cSN: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } Main.MyDataConstr_static_entry() // [] { [(cSO, Main.MyDataConstr_static_info: const iSQ_str-Main.MyDataConstr_static_info; const 1; const 7;)] } {offset cSO: R1 = R1 + 1; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } } -- LLVM ------------------------------------------------------------------------ %Main_zdtczqMyNewtypeConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyNewtypeConstr_closure$def = internal global %Main_zdtczqMyNewtypeConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGD_closure_struct* @rGD_closure$def to i64),i64 1), i64 -8101887544455363891, i64 4384341159368653246, i64 3}> @Main_zdtczqMyNewtypeConstr_closure = alias i8* bitcast (%Main_zdtczqMyNewtypeConstr_closure_struct* @Main_zdtczqMyNewtypeConstr_closure$def to i8*) %Main_zdtcMyNewtypeStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyNewtypeStruct_closure$def = internal global %Main_zdtcMyNewtypeStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGE_closure_struct* @rGE_closure$def to i64),i64 1), i64 2735651172251469986, i64 2399541496478989519, i64 3}> @Main_zdtcMyNewtypeStruct_closure = alias i8* bitcast (%Main_zdtcMyNewtypeStruct_closure_struct* @Main_zdtcMyNewtypeStruct_closure$def to i8*) %Main_zdtczqMyDataConstr_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtczqMyDataConstr_closure$def = internal global %Main_zdtczqMyDataConstr_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGF_closure_struct* @rGF_closure$def to i64),i64 1), i64 -5475190451886153665, i64 6686958652479025466, i64 3}> @Main_zdtczqMyDataConstr_closure = alias i8* bitcast (%Main_zdtczqMyDataConstr_closure_struct* @Main_zdtczqMyDataConstr_closure$def to i8*) %Main_zdtcMyDataStruct_closure_struct = type <{i64, i64, i64, i64, i64, i64}> @Main_zdtcMyDataStruct_closure$def = internal global %Main_zdtcMyDataStruct_closure_struct<{i64 ptrtoint (i8* @ghczmprim_GHCziTypes_TyCon_static_info to i64), i64 add (i64 ptrtoint (%Main_zdtrModule_closure_struct* @Main_zdtrModule_closure$def to i64),i64 1), i64 add (i64 ptrtoint (%rGG_closure_struct* @rGG_closure$def to i64),i64 1), i64 5826051442705447975, i64 -4331072423017222539, i64 3}> @Main_zdtcMyDataStruct_closure = alias i8* bitcast (%Main_zdtcMyDataStruct_closure_struct* @Main_zdtcMyDataStruct_closure$def to i8*) %Main_MyDataConstr_closure_struct = type <{i64}> @Main_MyDataConstr_closure$def = internal global %Main_MyDataConstr_closure_struct<{i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i64)}> @Main_MyDataConstr_closure = alias i8* bitcast (%Main_MyDataConstr_closure_struct* @Main_MyDataConstr_closure$def to i8*) @Main_MyDataConstr_info = internal alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_info$def to i8*) define internal ghccc void @Main_MyDataConstr_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 4294967301, i64 0, i64 15}> { cW0: ... ret void } @Main_MyDataConstr_con_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i8*) define ghccc void @Main_MyDataConstr_con_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWK_str_struct* @iWK_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_con_info$def to i64)),i64 0), i64 1, i64 2}> { ... } @Main_MyDataConstr_static_info = alias i8* bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i8*) define ghccc void @Main_MyDataConstr_static_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 add (i64 sub (i64 ptrtoint (%iWL_str_struct* @iWL_str$def to i64),i64 ptrtoint (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_MyDataConstr_static_info$def to i64)),i64 0), i64 1, i64 7}> { ... }
PS: Of course, the type newtype N
itself cannot disappear anywhere during compilation: a compiled module must export characters for use in other modules. In addition, you need somewhere to store pointers to the functions of the classes implemented by this type. The real benefit of a newtype
is that at a low level it is not necessary to go through a chain of constructors to get to the desired value.
In the previous paragraph, we implicitly determined why it is better to use newtype instead of data where it is possible (newtype is faster and more compact). Now the unresolved question is: why bother to use newtype — a type with one constructor and a field — when can I just use the original type or type is a synonym for it? There are many reasons for this.
Type synonyms are dereferenced during type inference, and newtype is always a separate type. Consider the following example:
newtype Height = Height Double newtype Weight = Weight Double newtype Percent = Percent Double newtype Age = Age Int diseaseRate :: Height -> Weight -> Age -> Percent diseaseRate (Height h) (Weight w) = _ diseaseRate' :: Double -> Double -> Int -> Double diseaseRate' hw = _
And the output of the compiler:
Example.hs:19:36: error: • Found hole: _ :: Age -> Percent • ... Example.hs:23:20: error: • Found hole: _ :: Int -> Double • ...
It is much easier to understand what type the function Age -> Percent
should have, than Int -> Double
. The famous lens library is a powerful tool, but I often dream about the types of its combinators in nightmares.
A very simple reason, but for some reason it is rarely mentioned in textbooks and tutorials. In the previous example, it is very easy to confuse height and weight as arguments of the diseaseRate'
function, but the compiler will not allow this to be done in the diseaseRate
function. Of course, this does not cancel the documentation, but is a very good addition to it.
If you do not want to produce a large number of new types for each function, there is a convenient technique - use tagging:
newtype Tagged tag a = Tagged { unTagged :: a }
You can tag enumerated types, or just use GHC.TypeLits
.
The first time I saw this reception was at the lecture of Simon Meyer .
Do we use Float
or Double
as the data type for percent output? Sometimes, the library user should not know this (the type may differ for different platforms, or we want to change it in a new version of the library).
The most popular reason. Creating a new type, we can implement some classes in a new way. For example, I want to display percentages in the line with the sign "%" after the number:
instance Show Percent where show (Percent t) = show t ++ "%"
But, generally, I would like to add and multiply the percentages; preferably without the need to override all Num
methods and the like. In GHC, for this there is an extension GeneralizedNewtypeDeriving
, which allows you to naturally display the implementation of a wide range of classes for newtype
types:
{-# LANGUAGE GeneralizedNewtypeDeriving #-} module Example where newtype Percent = Percent Double deriving (Eq, Ord, Num, Fractional, Floating, Real, RealFrac, RealFloat) instance Show Percent where show (Percent t) = show t ++ "%" x :: Percent x = 2 + Percent 4
There are many examples of using newtype
for various reasons. Maybe it is used even more often than data
. The first and foremost example is, of course, IO
. Just type in the ghci
console command :info IO
:
ghci> :info IO newtype IO a = GHC.Types.IO (GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, a #)) -- Defined in 'GHC.Types'
, IO
newtype
+. , STnewtype ST sa = ST (STRep sa)
.
transformersnewtype RWST rwsma = RWST { runRWST :: r -> s -> m (a, s, w) }
.
: Data.Semigroup Data.Monoid newtype
- . , ( newtype Max a = Max { getMax :: a }
) Ord
, Ord
Bounded
. !
Source: https://habr.com/ru/post/323526/
All Articles