on master help sign in
Network scale autodiff test
commitf9b53792fd2bf1f607773817a269620711fae63f authorHuw Campbell <huw.campbell@ambiata.com> dateTue 11 Apr 2017, 10:08 (10 years ago) parentffbbbf2
16 files changed+292−58
examples/main/gan-mnist.hs+1−1 grenade.cabal+1 test/Test/Grenade/Layers/Convolution.hs+8−6 test/Test/Grenade/Layers/FullyConnected.hs+3−3 test/Test/Grenade/Layers/Internal/Convolution.hs+1−1 test/Test/Grenade/Layers/Internal/Pooling.hs+1−1 test/Test/Grenade/Layers/Nonlinear.hs+3−5 test/Test/Grenade/Layers/PadCrop.hs+1−1 test/Test/Grenade/Layers/Pooling.hs+4−2 test/Test/Grenade/Recurrent/Layers/LSTM.hs+3−4 test/Test/Hedgehog/Compat.hs+39 test/Test/Jack/Hmatrix.hs → test/Test/Hedgehog/Hmatrix.hs+11−5 test/Test/Hedgehog/Network.hs+203 test/Test/Jack/TypeLits.hs → test/Test/Hedgehog/TypeLits.hs+10−7 test/Test/Jack/Compat.hs−22 test/test.hs+3
examples/main/gan-mnist.hs+1−1
@@ -11,7 +11,7 @@
1111-- of numbers similar to those in MNIST.
1212--
1313-- It demonstrates a different usage of the library. Within about 15
14−-- minutes hour it was producing examples like this:
14+-- minutes it was producing examples like this:
1515--
1616-- --.
1717-- .=-.--..#=###
grenade.cabal+1
@@ -137,6 +137,7 @@ test-suite test
137137 , random
138138 , ad
139139 , reflection
140+ , vector
140141
141142
142143benchmark bench
test/Test/Grenade/Layers/Convolution.hs+8−6
@@ -19,11 +19,12 @@ import Grenade.Core
1919import Grenade.Layers.Convolution
2020
2121import Hedgehog
22+import Hedgehog.Gen ( Gen )
2223import qualified Hedgehog.Gen as Gen
2324
24−import Test.Jack.Hmatrix
25−import Test.Jack.TypeLits
26−import Test.Jack.Compat
25+import Test.Hedgehog.Hmatrix
26+import Test.Hedgehog.TypeLits
27+import Test.Hedgehog.Compat
2728
2829data OpaqueConvolution :: * where
2930 OpaqueConvolution :: Convolution channels filters kernelRows kernelColumns strideRows strideColumns -> OpaqueConvolution
@@ -39,10 +40,11 @@ genConvolution :: ( KnownNat channels
3940 , KnownNat strideColumns
4041 , KnownNat kernelFlattened
4142 , kernelFlattened ~ (kernelRows * kernelColumns * channels)
42− ) => Jack (Convolution channels filters kernelRows kernelColumns strideRows strideColumns)
43+ , Monad m
44+ ) => Gen m (Convolution channels filters kernelRows kernelColumns strideRows strideColumns)
4345genConvolution = Convolution <$> uniformSample <*> uniformSample
4446
45−genOpaqueOpaqueConvolution :: Jack OpaqueConvolution
47+genOpaqueOpaqueConvolution :: Monad m => Gen m OpaqueConvolution
4648genOpaqueOpaqueConvolution = do
4749 channels <- genNat
4850 filters <- genNat
@@ -58,7 +60,7 @@ genOpaqueOpaqueConvolution = do
5860 p2 = natDict pkc
5961 p3 = natDict pch
6062 in case p1 %* p2 %* p3 of
61− Dict -> OpaqueConvolution <$> (genConvolution :: Jack (Convolution ch fl kr kc sr sc))
63+ Dict -> OpaqueConvolution <$> (genConvolution :: Monad n => Gen n (Convolution ch fl kr kc sr sc))
6264
6365prop_conv_net_witness = property $
6466 blindForAll genOpaqueOpaqueConvolution >>= \onet ->
test/Test/Grenade/Layers/FullyConnected.hs+3−3
@@ -17,8 +17,8 @@ import Grenade.Layers.FullyConnected
1717
1818import Hedgehog
1919
20−import Test.Jack.Compat
21−import Test.Jack.Hmatrix
20+import Test.Hedgehog.Compat
21+import Test.Hedgehog.Hmatrix
2222
2323data OpaqueFullyConnected :: * where
2424 OpaqueFullyConnected :: (KnownNat i, KnownNat o) => FullyConnected i o -> OpaqueFullyConnected
@@ -26,7 +26,7 @@ data OpaqueFullyConnected :: * where
2626instance Show OpaqueFullyConnected where
2727 show (OpaqueFullyConnected n) = show n
2828
29−genOpaqueFullyConnected :: Jack OpaqueFullyConnected
29+genOpaqueFullyConnected :: Monad m => Gen m OpaqueFullyConnected
3030genOpaqueFullyConnected = do
3131 input :: Integer <- choose 2 100
3232 output :: Integer <- choose 1 100
test/Test/Grenade/Layers/Internal/Convolution.hs+1−1
@@ -17,7 +17,7 @@ import qualified Hedgehog.Gen as Gen
1717import qualified Hedgehog.Range as Range
1818
1919import qualified Test.Grenade.Layers.Internal.Reference as Reference
20−import Test.Jack.Compat
20+import Test.Hedgehog.Compat
2121
2222prop_im2col_col2im_symmetrical_with_kernel_stride =
2323 let factors n = [x | x <- [1..n], n `mod` x == 0]
test/Test/Grenade/Layers/Internal/Pooling.hs+1−1
@@ -17,7 +17,7 @@ import qualified Hedgehog.Gen as Gen
1717import qualified Hedgehog.Range as Range
1818
1919import qualified Test.Grenade.Layers.Internal.Reference as Reference
20−import Test.Jack.Compat
20+import Test.Hedgehog.Compat
2121
2222prop_poolForwards_poolBackwards_behaves_as_reference =
2323 let ok extent kernel = [stride | stride <- [1..extent], (extent - kernel) `mod` stride == 0]
test/Test/Grenade/Layers/Nonlinear.hs+3−5
@@ -20,9 +20,9 @@ import GHC.TypeLits
2020
2121import Hedgehog
2222
23−import Test.Jack.Compat
24−import Test.Jack.Hmatrix
25−import Test.Jack.TypeLits
23+import Test.Hedgehog.Compat
24+import Test.Hedgehog.Hmatrix
25+import Test.Hedgehog.TypeLits
2626
2727import Numeric.LinearAlgebra.Static ( norm_Inf )
2828
@@ -68,8 +68,6 @@ prop_softmax_grad = property $
6868 in assert ((case numericalGradient - ret of
6969 (S1D x) -> norm_Inf x < 0.0001) :: Bool)
7070
71−
72−
7371tests :: IO Bool
7472tests = $$(checkConcurrent)
7573
test/Test/Grenade/Layers/PadCrop.hs+1−1
@@ -19,7 +19,7 @@ import Hedgehog
1919
2020import Numeric.LinearAlgebra.Static ( norm_Inf )
2121
22−import Test.Jack.Hmatrix
22+import Test.Hedgehog.Hmatrix
2323
2424prop_pad_crop :: Property
2525prop_pad_crop =
test/Test/Grenade/Layers/Pooling.hs+4−2
@@ -13,7 +13,9 @@ import GHC.TypeLits
1313import Grenade.Layers.Pooling
1414
1515import Hedgehog
16−import Test.Jack.Compat
16+import Hedgehog.Gen ( Gen )
17+
18+import Test.Hedgehog.Compat
1719
1820data OpaquePooling :: * where
1921 OpaquePooling :: (KnownNat kh, KnownNat kw, KnownNat sh, KnownNat sw) => Pooling kh kw sh sw -> OpaquePooling
@@ -21,7 +23,7 @@ data OpaquePooling :: * where
2123instance Show OpaquePooling where
2224 show (OpaquePooling n) = show n
2325
24−genOpaquePooling :: Jack OpaquePooling
26+genOpaquePooling :: Monad m => Gen m OpaquePooling
2527genOpaquePooling = do
2628 Just kernelHeight <- someNatVal <$> choose 2 15
2729 Just kernelWidth <- someNatVal <$> choose 2 15
test/Test/Grenade/Recurrent/Layers/LSTM.hs+3−4
@@ -11,6 +11,7 @@
1111module Test.Grenade.Recurrent.Layers.LSTM where
1212
1313import Hedgehog
14+import Hedgehog.Gen ( Gen )
1415import Hedgehog.Internal.Source
1516import Hedgehog.Internal.Show
1617import Hedgehog.Internal.Property ( failWith, Diff (..) )
@@ -26,10 +27,9 @@ import qualified Numeric.LinearAlgebra.Static as S
2627
2728
2829import qualified Test.Grenade.Recurrent.Layers.LSTM.Reference as Reference
29−import Test.Jack.Hmatrix
30−import Test.Jack.Compat
30+import Test.Hedgehog.Hmatrix
3131
32−genLSTM :: forall i o. (KnownNat i, KnownNat o) => Jack (LSTM i o)
32+genLSTM :: forall i o m. (KnownNat i, KnownNat o, Monad m) => Gen m (LSTM i o)
3333genLSTM = do
3434 let w = uniformSample
3535 u = uniformSample
@@ -121,6 +121,5 @@ prop_lstm_reference_backwards_cell =
121121 failWith (Just $ Diff "Failed (" "- lhs" "~/~" "+ rhs" ")" diff) ""
122122infix 4 ~~~
123123
124−
125124tests :: IO Bool
126125tests = $$(checkConcurrent)
test/Test/Hedgehog/Compat.hsnew file+39
@@ -0,0 +1,39 @@
1+{-# LANGUAGE RankNTypes #-}
2+module Test.Hedgehog.Compat where
3+
4+import Control.Monad.Trans.Class (MonadTrans(..))
5+
6+import Data.Typeable ( typeOf )
7+
8+import Hedgehog.Gen ( Gen )
9+import qualified Hedgehog.Gen as Gen
10+import qualified Hedgehog.Range as Range
11+import Hedgehog.Internal.Property
12+import Hedgehog.Internal.Source
13+import Hedgehog.Internal.Show
14+
15+(...) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
16+(...) = (.) . (.)
17+{-# INLINE (...) #-}
18+
19+choose :: ( Monad m, Integral a ) => a -> a -> Gen m a
20+choose = Gen.integral ... Range.constant
21+
22+-- | Generates a random input for the test by running the provided generator.
23+blindForAll :: Monad m => Gen m a -> Test m a
24+blindForAll = Test . lift . lift
25+
26+-- | Generates a random input for the test by running the provided generator.
27+semiBlindForAll :: (Monad m, Show a, HasCallStack) => Gen m a -> Test m a
28+semiBlindForAll gen = do
29+ x <- Test . lift $ lift gen
30+ writeLog $ Input (getCaller callStack) (typeOf ()) (showPretty x)
31+ return x
32+
33+
34+-- | Generates a random input for the test by running the provided generator.
35+forAllRender :: (Monad m, HasCallStack) => ( a -> String ) -> Gen m a -> Test m a
36+forAllRender render gen = do
37+ x <- Test . lift $ lift gen
38+ writeLog $ Input (getCaller callStack) (typeOf ()) (render x)
39+ return x
test/Test/Jack/Hmatrix.hs → test/Test/Hedgehog/Hmatrix.hsrenamed+11−5
@@ -3,29 +3,35 @@
33{-# LANGUAGE ScopedTypeVariables #-}
44{-# LANGUAGE GADTs #-}
55
6−module Test.Jack.Hmatrix where
6+module Test.Hedgehog.Hmatrix where
77
88import Grenade
99import Data.Singletons
1010
11+import Hedgehog.Gen ( Gen )
1112import qualified Hedgehog.Gen as Gen
1213import qualified Hedgehog.Range as Range
1314
1415import GHC.TypeLits
1516
1617import qualified Numeric.LinearAlgebra.Static as HStatic
17−import Test.Jack.Compat
1818
19−randomVector :: forall n. KnownNat n => Jack (HStatic.R n)
19+randomVector :: forall m n. ( Monad m, KnownNat n ) => Gen m (HStatic.R n)
2020randomVector = (\s -> HStatic.randomVector s HStatic.Uniform * 2 - 1) <$> Gen.int Range.linearBounded
2121
22−uniformSample :: forall m n. (KnownNat m, KnownNat n) => Jack (HStatic.L m n)
22+uniformSample :: forall mm m n. ( Monad mm, KnownNat m, KnownNat n ) => Gen mm (HStatic.L m n)
2323uniformSample = (\s -> HStatic.uniformSample s (-1) 1 ) <$> Gen.int Range.linearBounded
2424
2525-- | Generate random data of the desired shape
26−genOfShape :: forall x. ( SingI x ) => Jack (S x)
26+genOfShape :: forall m x. ( Monad m, SingI x ) => Gen m (S x)
2727genOfShape =
2828 case (sing :: Sing x) of
2929 D1Sing -> S1D <$> randomVector
3030 D2Sing -> S2D <$> uniformSample
3131 D3Sing -> S3D <$> uniformSample
32+
33+
34+nice :: S shape -> String
35+nice (S1D x) = show . HStatic.extract $ x
36+nice (S2D x) = show . HStatic.extract $ x
37+nice (S3D x) = show . HStatic.extract $ x
test/Test/Hedgehog/Network.hsnew file+203
@@ -0,0 +1,203 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE RankNTypes #-}
3+{-# LANGUAGE DataKinds #-}
4+{-# LANGUAGE ScopedTypeVariables #-}
5+{-# LANGUAGE PolyKinds #-}
6+{-# LANGUAGE GADTs #-}
7+{-# LANGUAGE TypeOperators #-}
8+{-# LANGUAGE TemplateHaskell #-}
9+{-# LANGUAGE FlexibleContexts #-}
10+module Test.Hedgehog.Network where
11+
12+import Control.Monad.ST ( runST )
13+
14+import Data.Constraint
15+#if __GLASGOW_HASKELL__ < 800
16+import Data.Proxy
17+#endif
18+import qualified Data.Vector.Storable as VS
19+import qualified Data.Vector.Storable.Mutable as VS ( write )
20+import Data.Singletons
21+import Data.Singletons.Prelude.List
22+-- import Data.Type.Equality
23+
24+import Hedgehog
25+import Hedgehog.Gen ( Gen )
26+import qualified Hedgehog.Gen as Gen
27+import Hedgehog.Internal.Source
28+import Hedgehog.Internal.Property ( failWith )
29+
30+import Grenade
31+
32+import GHC.TypeLits
33+import GHC.TypeLits.Witnesses
34+import Test.Hedgehog.Compat
35+import Test.Hedgehog.TypeLits
36+import Test.Hedgehog.Hmatrix
37+import Test.Grenade.Layers.Convolution
38+
39+import Numeric.LinearAlgebra ( flatten )
40+import Numeric.LinearAlgebra.Static ( size , extract, norm_Inf )
41+import Unsafe.Coerce
42+
43+data SomeNetwork :: * where
44+ SomeNetwork :: ( SingI shapes, SingI (Head shapes), SingI (Last shapes), Show (Network layers shapes) ) => Network layers shapes -> SomeNetwork
45+
46+instance Show SomeNetwork where
47+ show (SomeNetwork net) = show net
48+
49+-- | Generate a random network of a random type
50+--
51+-- This is slightly insane
52+genNetwork :: Monad m => Gen m SomeNetwork
53+genNetwork =
54+ Gen.recursive Gen.choice [
55+ do SomeSing ( r :: Sing final ) <- genShape
56+ withSingI r $
57+ pure (SomeNetwork (NNil :: Network '[] '[ final ] ))
58+ ] [
59+ do SomeNetwork ( rest :: Network layers shapes ) <- genNetwork
60+ case ( sing :: Sing shapes ) of
61+ SNil -> Gen.discard
62+ SCons ( r :: Sing h ) ( _ :: Sing hs ) ->
63+ withSingI r $ Gen.choice [
64+ pure (SomeNetwork (Logit :~> rest :: Network ( Logit ': layers ) ( h ': h ': hs )))
65+ , pure (SomeNetwork (Tanh :~> rest :: Network ( Tanh ': layers ) ( h ': h ': hs )))
66+ , case r of
67+ D1Sing ->
68+ Gen.choice [
69+ pure (SomeNetwork (Relu :~> rest :: Network ( Relu ': layers ) ( h ': h ': hs )))
70+ , pure (SomeNetwork (Elu :~> rest :: Network ( Elu ': layers ) ( h ': h ': hs )))
71+ , pure (SomeNetwork (Softmax :~> rest :: Network ( Softmax ': layers ) ( h ': h ': hs )))
72+ ]
73+ D2Sing ->
74+ Gen.choice [
75+ pure (SomeNetwork (Relu :~> rest :: Network ( Relu ': layers ) ( h ': h ': hs )))
76+ , pure (SomeNetwork (Elu :~> rest :: Network ( Elu ': layers ) ( h ': h ': hs )))
77+ , do -- Build a convolution layer with one filter output
78+ -- Figure out some kernel sizes which work for this layer
79+ -- There must be a better way than this...
80+ let dumb :: S h = 0
81+ case dumb of
82+ S2D x -> do
83+ let (rs, cs) = size x
84+ let output_r = fromIntegral rs
85+ let output_c = fromIntegral cs
86+
87+ let ok extent kernel = [stride | stride <- [ 1 .. extent ], (extent - kernel) `mod` stride == 0]
88+
89+ -- Get some kernels which will fit
90+ kernel_r <- choose 1 output_r
91+ kernel_c <- choose 1 output_c
92+
93+ -- Build up some strides which also fit
94+ stride_r <- Gen.element $ ok output_r kernel_r
95+ stride_c <- Gen.element $ ok output_c kernel_c
96+
97+ -- Determine the input size
98+ let input_r = (output_r - 1) * stride_r + kernel_r
99+ let input_c = (output_c - 1) * stride_c + kernel_c
100+
101+ -- Remake types for input
102+ case ( someNatVal input_r, someNatVal input_c, someNatVal output_r, someNatVal output_c, someNatVal kernel_r, someNatVal kernel_c, someNatVal stride_r, someNatVal stride_c ) of
103+ ( Just (SomeNat (_ :: Proxy inRows)), Just (SomeNat (_ :: Proxy inCols)),
104+ Just (SomeNat (_ :: Proxy outRows)), Just (SomeNat (_ :: Proxy outCols)),
105+ Just (SomeNat (pkr :: Proxy kernelRows)), Just (SomeNat (pkc :: Proxy kernelCols)),
106+ Just (SomeNat (_ :: Proxy strideRows)), Just (SomeNat (_ :: Proxy strideCols))) ->
107+ let p1 = natDict pkr
108+ p2 = natDict pkc
109+ in case ( p1 %* p2
110+ -- Fake it till you make it.
111+ , (unsafeCoerce (Dict :: Dict ()) :: Dict ( ( 'D2 outRows outCols ) ~ h ))
112+ , (unsafeCoerce (Dict :: Dict ()) :: Dict (((outRows - 1) * strideRows) ~ (inRows - kernelRows)))
113+ , (unsafeCoerce (Dict :: Dict ()) :: Dict (((outCols - 1) * strideCols) ~ (inCols - kernelCols)))) of
114+ (Dict, Dict, Dict, Dict) -> do
115+ conv <- genConvolution
116+ pure (SomeNetwork (conv :~> rest :: Network ( Convolution 1 1 kernelRows kernelCols strideRows strideCols ': layers ) ( ('D2 inRows inCols) ': h ': hs )))
117+ _ -> Gen.discard
118+ ]
119+ D3Sing ->
120+ Gen.choice [
121+ pure (SomeNetwork (Relu :~> rest :: Network ( Relu ': layers ) ( h ': h ': hs )))
122+ , pure (SomeNetwork (Elu :~> rest :: Network ( Elu ': layers ) ( h ': h ': hs )))
123+ ]
124+ ]
125+ ]
126+
127+-- Test a partial derivative numerically for a random network and input
128+prop_auto_diff :: Property
129+prop_auto_diff = property $ do
130+ SomeNetwork (network :: Network layers shapes) <- forAll genNetwork
131+ (input :: S (Head shapes)) <- forAllRender nice genOfShape
132+ (target :: S (Last shapes)) <- forAllRender nice oneUp
133+ (tested :: S (Head shapes)) <- forAllRender nice oneUp
134+
135+ let (tapes, output) = runNetwork network input
136+ let (_, bgrad) = runGradient network tapes target
137+ let inputDiff = input + tested * 0.00001
138+ let expected = maxVal ( bgrad * tested )
139+ let (_, outputDiff) = runNetwork network inputDiff
140+ let result = maxVal ( outputDiff * target - output * target ) / 0.00001
141+
142+ result ~~~ expected
143+
144+ where
145+
146+-- Make a shape where all are 0 except for 1 value, which is 1.
147+oneUp :: forall shape m. ( Monad m, SingI shape ) => Gen m (S shape)
148+oneUp =
149+ case ( sing :: Sing shape ) of
150+ D1Sing -> let x = 0 :: S ( shape )
151+ in case x of
152+ ( S1D x' ) -> do
153+ let ex = extract x'
154+ let len = VS.length ex
155+ ix <- choose 0 (len - 1)
156+ let nx = runST $ do ex' <- VS.thaw ex
157+ VS.write ex' ix 1.0
158+ VS.freeze ex'
159+ maybe Gen.discard pure . fromStorable $ nx
160+
161+ D2Sing -> let x = 0 :: S ( shape )
162+ in case x of
163+ ( S2D x' ) -> do
164+ let ex = flatten ( extract x' )
165+ let len = VS.length ex
166+ ix <- choose 0 (len - 1)
167+ let nx = runST $ do ex' <- VS.thaw ex
168+ VS.write ex' ix 1
169+ VS.freeze ex'
170+ maybe Gen.discard pure . fromStorable $ nx
171+
172+ D3Sing -> let x = 0 :: S ( shape )
173+ in case x of
174+ ( S3D x' ) -> do
175+ let ex = flatten ( extract x' )
176+ let len = VS.length ex
177+ ix <- choose 0 (len - 1)
178+ let nx = runST $ do ex' <- VS.thaw ex
179+ VS.write ex' ix 1
180+ VS.freeze ex'
181+ maybe Gen.discard pure . fromStorable $ nx
182+
183+maxVal :: S shape -> Double
184+maxVal ( S1D x ) = norm_Inf x
185+maxVal ( S2D x ) = norm_Inf x
186+maxVal ( S3D x ) = norm_Inf x
187+
188+(~~~) :: (Monad m, HasCallStack) => Double -> Double -> Test m ()
189+(~~~) x y =
190+ if (x - y) < 1e-5 then
191+ success
192+ else
193+ withFrozenCallStack $
194+ failWith Nothing $ unlines [
195+ "━━━ Not Simliar ━━━"
196+ , show x
197+ , show y
198+ ]
199+infix 4 ~~~
200+
201+
202+tests :: IO Bool
203+tests = $$(checkConcurrent)
test/Test/Jack/TypeLits.hs → test/Test/Hedgehog/TypeLits.hsrenamed+10−7
@@ -3,7 +3,9 @@
33{-# LANGUAGE DataKinds #-}
44{-# LANGUAGE ScopedTypeVariables #-}
55{-# LANGUAGE PolyKinds #-}
6−module Test.Jack.TypeLits where
6+{-# LANGUAGE TypeOperators #-}
7+{-# LANGUAGE GADTs #-}
8+module Test.Hedgehog.TypeLits where
79
810import Data.Constraint
911#if __GLASGOW_HASKELL__ < 800
@@ -11,15 +13,16 @@ import Data.Proxy
1113#endif
1214import Data.Singletons
1315
16+import Hedgehog.Gen ( Gen )
1417import qualified Hedgehog.Gen as Gen
1518
1619import Grenade
1720
1821import GHC.TypeLits
1922import GHC.TypeLits.Witnesses
20−import Test.Jack.Compat
23+import Test.Hedgehog.Compat
2124
22−genNat :: Jack SomeNat
25+genNat :: Monad m => Gen m SomeNat
2326genNat = do
2427 Just n <- someNatVal <$> choose 1 10
2528 return n
@@ -30,7 +33,7 @@ type Shape' = ('KProxy :: KProxy Shape)
3033type Shape' = Shape
3134#endif
3235
33−genShape :: Jack (SomeSing Shape')
36+genShape :: Monad m => Gen m (SomeSing Shape')
3437genShape
3538 = Gen.choice [
3639 genD1
@@ -38,20 +41,20 @@ genShape
3841 , genD3
3942 ]
4043
41−genD1 :: Jack (SomeSing Shape')
44+genD1 :: Monad m => Gen m (SomeSing Shape')
4245genD1 = do
4346 n <- genNat
4447 return $ case n of
4548 SomeNat (_ :: Proxy x) -> SomeSing (sing :: Sing ('D1 x))
4649
47−genD2 :: Jack (SomeSing Shape')
50+genD2 :: Monad m => Gen m (SomeSing Shape')
4851genD2 = do
4952 n <- genNat
5053 m <- genNat
5154 return $ case (n, m) of
5255 (SomeNat (_ :: Proxy x), SomeNat (_ :: Proxy y)) -> SomeSing (sing :: Sing ('D2 x y))
5356
54−genD3 :: Jack (SomeSing Shape')
57+genD3 :: Monad m => Gen m (SomeSing Shape')
5558genD3 = do
5659 n <- genNat
5760 m <- genNat
test/Test/Jack/Compat.hsdeleted−22
@@ -1,22 +0,0 @@
1−{-# LANGUAGE RankNTypes #-}
2−module Test.Jack.Compat where
3−
4−import Control.Monad.Trans.Class (MonadTrans(..))
5−
6−import Hedgehog
7−import qualified Hedgehog.Gen as Gen
8−import qualified Hedgehog.Range as Range
9−import Hedgehog.Internal.Property ( Test (..) )
10−
11−type Jack x = forall m. Monad m => Gen m x
12−
13−(...) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
14−(...) = (.) . (.)
15−{-# INLINE (...) #-}
16−
17−choose :: Integral a => a -> a -> Jack a
18−choose = Gen.integral ... Range.constant
19−
20−-- | Generates a random input for the test by running the provided generator.
21−blindForAll :: Monad m => Gen m a -> Test m a
22−blindForAll = Test . lift . lift
test/test.hs+3
@@ -10,6 +10,7 @@ import qualified Test.Grenade.Layers.Internal.Convolution
1010import qualified Test.Grenade.Layers.Internal.Pooling
1111
1212import qualified Test.Grenade.Recurrent.Layers.LSTM
13+import qualified Test.Hedgehog.Network
1314
1415import System.Exit
1516import System.IO
@@ -27,6 +28,8 @@ main =
2728 , Test.Grenade.Layers.Internal.Pooling.tests
2829
2930 , Test.Grenade.Recurrent.Layers.LSTM.tests
31+
32+ , Test.Hedgehog.Network.tests
3033 ]
3134
3235disorderMain :: [IO Bool] -> IO ()