Ticket #2396: ClassMethodInline.hs

File ClassMethodInline.hs, 3.7 KB (added by sedillard, 4 years ago)

program exhibiting the bug

Line 
1-- BUG : default class methods are not inlined
2-- compile with -O2
3-- see class PackedMat for more details
4
5
6{-# LANGUAGE EmptyDataDecls #-}
7{-# LANGUAGE ExistentialQuantification #-}
8{-# LANGUAGE FlexibleInstances #-}
9{-# LANGUAGE FlexibleContexts #-}
10{-# LANGUAGE FunctionalDependencies #-}
11{-# LANGUAGE MultiParamTypeClasses #-}
12{-# LANGUAGE NoMonomorphismRestriction #-}
13{-# LANGUAGE ScopedTypeVariables #-}
14{-# LANGUAGE TypeOperators #-}
15{-# LANGUAGE TypeSynonymInstances #-}
16{-# LANGUAGE UndecidableInstances #-}
17
18module Test where
19
20import Prelude hiding (map,zipWith,foldr,foldl)
21
22data (:.) a b = !a :. !b
23infixr :.
24type Vec3 a = a:.a:.a:.()
25type Mat33 a = Vec3 (Vec3 a)
26type Mat33D = Vec3 Vec3D 
27data Vec3D = Vec3D {-#UNPACK#-} !Double 
28                   {-#UNPACK#-} !Double 
29                   {-#UNPACK#-} !Double
30
31-- This is the class in question
32class (Map pv v pm m, Map v pv m pm, PackedVec pv v) 
33    => PackedMat pv v pm m | pv -> v, pm -> m
34  where
35    packMat   :: m -> pm
36    unpackMat :: pm -> m
37    -- These default definitions are not inlined.
38    -- See instance declaration below.
39    packMat = map pack
40    unpackMat = map unpack
41    {-# INLINE packMat #-}
42    {-# INLINE unpackMat #-}
43
44-- BUG IS HERE !!!
45instance PackedMat Vec3D (Vec3 Double) Mat33D (Mat33 Double)
46-- Uncomment these method definitions to see the desired behavior.
47-- As it stands, core for definition of multmv3d will call
48-- unpackMat and use many unessecary constructors
49--  where
50--    packMat = map pack
51--    unpackMat = map unpack
52--    {-# INLINE packMat #-}
53--    {-# INLINE unpackMat #-}
54
55
56-- Of course this suffices without the class:
57{-
58packM = V.map packV
59unpackM = V.map unpackV
60{-# INLINE packM #-}
61{-# INLINE unpackM #-}
62-}
63
64class PackedVec pv v | pv -> v where
65  pack   :: v -> pv
66  unpack :: pv -> v
67
68instance PackedVec Vec3D (Vec3 Double) where
69  pack (x:.y:.z:.()) = Vec3D x y z
70  unpack (Vec3D x y z) = x:.y:.z:.()
71  {-# INLINE pack #-}
72  {-# INLINE unpack #-}
73
74
75multmv3d :: Mat33D -> Vec3D -> Vec3D
76multmv3d a b = pack $ unpackMat a `multmv` unpack b
77
78multmv :: (Num a, ZipWith a a a v v v, Fold a v, Map v a m v') 
79          => m -> v -> v'
80
81multmv m v = map (fold (+) . zipWith (*) v) m
82{-# INLINE multmv #-}
83
84class Map a b u v | u -> a, v -> b, b u -> v, a v -> u where
85  map :: (a -> b) -> u -> v
86
87instance Map a b (a :. ()) (b :. ()) where
88  map f (x :. ()) = (f x) :. ()
89  {-# INLINE map #-}
90
91instance Map a b (a':.u) (b':.v) => Map a b (a:.a':.u) (b:.b':.v) where
92  map f (x:.v) = (f x):.(map f v)
93  {-# INLINE map #-}
94
95
96class Fold a v | v -> a where
97  fold  :: (a -> a -> a) -> v -> a
98  foldl :: (b -> a -> b) -> b -> v -> b
99  foldr :: (a -> b -> b) -> b -> v -> b
100
101instance Fold a (a:.()) where
102  fold  f   (a:._) = a
103  foldl f z (a:._) = (f $! z) $! a
104  foldr f z (a:._) = (f $! a) $! z
105  {-# INLINE fold #-}
106  {-# INLINE foldl #-}
107  {-# INLINE foldr #-}
108
109instance Fold a (a':.u) => Fold a (a:.a':.u) where
110  fold  f   (a:.v) = (f $! a) $! (fold f v)
111  foldl f z (a:.v) = (f $! (foldl f z v)) $! a
112  foldr f z (a:.v) = (f $! a) $! (foldr f z v)
113  {-# INLINE fold #-}
114  {-# INLINE foldl #-}
115  {-# INLINE foldr #-}
116
117
118class ZipWith a b c u v w | u->a, v->b, w->c, u v c -> w where
119  zipWith :: (a -> b -> c) -> u -> v -> w
120
121instance ZipWith a b c (a:.()) (b:.()) (c:.()) where
122  zipWith f (x:._) (y:._) = f x y :.()
123  {-# INLINE zipWith #-}
124
125instance ZipWith a b c (a:.()) (b:.b:.bs) (c:.()) where
126  zipWith f (x:._) (y:._) = f x y :.()
127  {-# INLINE zipWith #-}
128
129instance ZipWith a b c (a:.a:.as) (b:.()) (c:.()) where
130  zipWith f (x:._) (y:._) = f x y :.()
131  {-# INLINE zipWith #-}
132
133instance 
134  ZipWith a b c (a':.u) (b':.v) (c':.w) 
135  => ZipWith a b c (a:.a':.u) (b:.b':.v) (c:.c':.w) 
136    where
137      zipWith f (x:.u) (y:.v) = f x y :. zipWith f u v
138      {-# INLINE zipWith #-}