| 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 | |
|---|
| 18 | module Test where |
|---|
| 19 | |
|---|
| 20 | import Prelude hiding (map,zipWith,foldr,foldl) |
|---|
| 21 | |
|---|
| 22 | data (:.) a b = !a :. !b |
|---|
| 23 | infixr :. |
|---|
| 24 | type Vec3 a = a:.a:.a:.() |
|---|
| 25 | type Mat33 a = Vec3 (Vec3 a) |
|---|
| 26 | type Mat33D = Vec3 Vec3D |
|---|
| 27 | data Vec3D = Vec3D {-#UNPACK#-} !Double |
|---|
| 28 | {-#UNPACK#-} !Double |
|---|
| 29 | {-#UNPACK#-} !Double |
|---|
| 30 | |
|---|
| 31 | -- This is the class in question |
|---|
| 32 | class (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 !!! |
|---|
| 45 | instance 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 | {- |
|---|
| 58 | packM = V.map packV |
|---|
| 59 | unpackM = V.map unpackV |
|---|
| 60 | {-# INLINE packM #-} |
|---|
| 61 | {-# INLINE unpackM #-} |
|---|
| 62 | -} |
|---|
| 63 | |
|---|
| 64 | class PackedVec pv v | pv -> v where |
|---|
| 65 | pack :: v -> pv |
|---|
| 66 | unpack :: pv -> v |
|---|
| 67 | |
|---|
| 68 | instance 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 | |
|---|
| 75 | multmv3d :: Mat33D -> Vec3D -> Vec3D |
|---|
| 76 | multmv3d a b = pack $ unpackMat a `multmv` unpack b |
|---|
| 77 | |
|---|
| 78 | multmv :: (Num a, ZipWith a a a v v v, Fold a v, Map v a m v') |
|---|
| 79 | => m -> v -> v' |
|---|
| 80 | |
|---|
| 81 | multmv m v = map (fold (+) . zipWith (*) v) m |
|---|
| 82 | {-# INLINE multmv #-} |
|---|
| 83 | |
|---|
| 84 | class Map a b u v | u -> a, v -> b, b u -> v, a v -> u where |
|---|
| 85 | map :: (a -> b) -> u -> v |
|---|
| 86 | |
|---|
| 87 | instance Map a b (a :. ()) (b :. ()) where |
|---|
| 88 | map f (x :. ()) = (f x) :. () |
|---|
| 89 | {-# INLINE map #-} |
|---|
| 90 | |
|---|
| 91 | instance 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 | |
|---|
| 96 | class 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 | |
|---|
| 101 | instance 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 | |
|---|
| 109 | instance 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 | |
|---|
| 118 | class 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 | |
|---|
| 121 | instance ZipWith a b c (a:.()) (b:.()) (c:.()) where |
|---|
| 122 | zipWith f (x:._) (y:._) = f x y :.() |
|---|
| 123 | {-# INLINE zipWith #-} |
|---|
| 124 | |
|---|
| 125 | instance ZipWith a b c (a:.()) (b:.b:.bs) (c:.()) where |
|---|
| 126 | zipWith f (x:._) (y:._) = f x y :.() |
|---|
| 127 | {-# INLINE zipWith #-} |
|---|
| 128 | |
|---|
| 129 | instance ZipWith a b c (a:.a:.as) (b:.()) (c:.()) where |
|---|
| 130 | zipWith f (x:._) (y:._) = f x y :.() |
|---|
| 131 | {-# INLINE zipWith #-} |
|---|
| 132 | |
|---|
| 133 | instance |
|---|
| 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 #-} |
|---|