From 1539783ee5f4928a992eef0bfc3293bbb8ee31ea Mon Sep 17 00:00:00 2001 From: Judah Jacobson Date: Mon, 28 Nov 2016 21:15:09 -0800 Subject: [PATCH] Update type constraints to work around a ghc-8 bug. (#47) Also removes all the ghc-8-specific logic in the .cabal files. ghc-8 has issues with deeply nested tuples of constraints. We can work around it by: - Changing TensorTypes to a regular class. This required FlexibleContexts. (But we'll probably need it anyway when we support heterogeneous tensor lists.) - Specializing NoneOf for long type lists. For more details, see: https://ghc.haskell.org/trac/ghc/ticket/12175. Also added 'directory' to tensorflow-core-ops' dependencies since it's used in the Setup script. One more step towards fixing #38. --- tensorflow-core-ops/tensorflow-core-ops.cabal | 5 +---- tensorflow-nn/src/TensorFlow/NN.hs | 1 + tensorflow-nn/tensorflow-nn.cabal | 4 ---- tensorflow-opgen/src/TensorFlow/OpGen.hs | 1 + tensorflow-ops/src/TensorFlow/EmbeddingOps.hs | 1 + tensorflow-ops/src/TensorFlow/Ops.hs | 1 + tensorflow-ops/tensorflow-ops.cabal | 9 --------- tensorflow-ops/tests/TypesTest.hs | 1 + tensorflow/src/TensorFlow/Types.hs | 18 +++++++++++++----- 9 files changed, 19 insertions(+), 22 deletions(-) diff --git a/tensorflow-core-ops/tensorflow-core-ops.cabal b/tensorflow-core-ops/tensorflow-core-ops.cabal index 701bd6b..a25695c 100644 --- a/tensorflow-core-ops/tensorflow-core-ops.cabal +++ b/tensorflow-core-ops/tensorflow-core-ops.cabal @@ -15,6 +15,7 @@ library exposed-modules: TensorFlow.GenOps.Core build-depends: Cabal >= 1.22 && < 1.25 , bytestring + , directory , proto-lens == 0.1.* , tensorflow-opgen == 0.1.* , tensorflow == 0.1.* @@ -24,10 +25,6 @@ library , lens-family , text default-language: Haskell2010 - -- Work around https://ghc.haskell.org/trac/ghc/ticket/12175. - if impl(ghc >= 8) { - ghc-options: -fconstraint-solver-iterations=0 - } source-repository head type: git diff --git a/tensorflow-nn/src/TensorFlow/NN.hs b/tensorflow-nn/src/TensorFlow/NN.hs index 9c51272..5b6f60f 100644 --- a/tensorflow-nn/src/TensorFlow/NN.hs +++ b/tensorflow-nn/src/TensorFlow/NN.hs @@ -13,6 +13,7 @@ -- limitations under the License. {-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} module TensorFlow.NN diff --git a/tensorflow-nn/tensorflow-nn.cabal b/tensorflow-nn/tensorflow-nn.cabal index 5c3ae5b..ca51474 100644 --- a/tensorflow-nn/tensorflow-nn.cabal +++ b/tensorflow-nn/tensorflow-nn.cabal @@ -19,10 +19,6 @@ library , tensorflow == 0.1.* , tensorflow-ops == 0.1.* default-language: Haskell2010 - -- Work around https://ghc.haskell.org/trac/ghc/ticket/12175. - if impl(ghc >= 8) { - ghc-options: -fconstraint-solver-iterations=0 - } Test-Suite NNTest diff --git a/tensorflow-opgen/src/TensorFlow/OpGen.hs b/tensorflow-opgen/src/TensorFlow/OpGen.hs index 32b497b..2bca901 100644 --- a/tensorflow-opgen/src/TensorFlow/OpGen.hs +++ b/tensorflow-opgen/src/TensorFlow/OpGen.hs @@ -117,6 +117,7 @@ docOpList :: OpGenFlags -> OpList -> Doc docOpList flags opList = stack [ "{-# LANGUAGE ConstraintKinds #-}" , "{-# LANGUAGE DataKinds #-}" + , "{-# LANGUAGE FlexibleContexts #-}" , "{-# LANGUAGE FlexibleInstances #-}" , "{-# LANGUAGE OverloadedStrings #-}" , "{-# LANGUAGE ScopedTypeVariables #-}" diff --git a/tensorflow-ops/src/TensorFlow/EmbeddingOps.hs b/tensorflow-ops/src/TensorFlow/EmbeddingOps.hs index 12605b8..43da0e5 100644 --- a/tensorflow-ops/src/TensorFlow/EmbeddingOps.hs +++ b/tensorflow-ops/src/TensorFlow/EmbeddingOps.hs @@ -14,6 +14,7 @@ {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} diff --git a/tensorflow-ops/src/TensorFlow/Ops.hs b/tensorflow-ops/src/TensorFlow/Ops.hs index e9fa3f5..7e33696 100644 --- a/tensorflow-ops/src/TensorFlow/Ops.hs +++ b/tensorflow-ops/src/TensorFlow/Ops.hs @@ -46,6 +46,7 @@ -- TensorFlow uses to avoid common subexpression elimination.) {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} diff --git a/tensorflow-ops/tensorflow-ops.cabal b/tensorflow-ops/tensorflow-ops.cabal index cf5716a..b6b60ad 100644 --- a/tensorflow-ops/tensorflow-ops.cabal +++ b/tensorflow-ops/tensorflow-ops.cabal @@ -29,10 +29,6 @@ library , tensorflow-core-ops == 0.1.* , text default-language: Haskell2010 - -- Work around https://ghc.haskell.org/trac/ghc/ticket/12175. - if impl(ghc >= 8) { - ghc-options: -fconstraint-solver-iterations=0 - } Test-Suite BuildTest default-language: Haskell2010 @@ -206,11 +202,6 @@ Test-Suite TypesTest , test-framework-hunit , test-framework-quickcheck2 , vector - -- Work around https://ghc.haskell.org/trac/ghc/ticket/12175, - -- since this test defines its own ops. - if impl(ghc >= 8) { - ghc-options: -fconstraint-solver-iterations=0 - } Benchmark FeedFetchBench default-language: Haskell2010 diff --git a/tensorflow-ops/tests/TypesTest.hs b/tensorflow-ops/tests/TypesTest.hs index 6237bd2..3364a1a 100644 --- a/tensorflow-ops/tests/TypesTest.hs +++ b/tensorflow-ops/tests/TypesTest.hs @@ -14,6 +14,7 @@ {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} diff --git a/tensorflow/src/TensorFlow/Types.hs b/tensorflow/src/TensorFlow/Types.hs index 2c9c193..f3a9b41 100644 --- a/tensorflow/src/TensorFlow/Types.hs +++ b/tensorflow/src/TensorFlow/Types.hs @@ -16,6 +16,7 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} @@ -330,11 +331,11 @@ instance Attribute [Int64] where type OneOf ts a = (TensorType a, TensorTypes ts, NoneOf (AllTensorTypes \\ ts) a) --- | A 'Constraint' checking that the input is a list of 'TensorType's. +-- | A check that the input is a list of 'TensorType's. -- Helps improve error messages when using 'OneOf'. -type family TensorTypes ts :: Constraint where - TensorTypes '[] = () - TensorTypes (t ': ts) = (TensorType t, TensorTypes ts) +class TensorTypes (ts :: [*]) where +instance TensorTypes '[] +instance (TensorType t, TensorTypes ts) => TensorTypes (t ': ts) -- | A constraint checking that two types are different. type family a /= b :: Constraint where @@ -378,5 +379,12 @@ type family as \\ bs where -- | A constraint that the type @a@ doesn't appear in the type list @ts@. -- Assumes that @a@ and each of the elements of @ts@ are 'TensorType's. type family NoneOf ts a :: Constraint where + -- Specialize this type family when `ts` is a long list, to avoid deeply + -- nested tuples of constraints. Works around a bug in ghc-8: + -- https://ghc.haskell.org/trac/ghc/ticket/12175 + NoneOf (t1 ': t2 ': t3 ': t4 ': ts) a + = (a /= t1, a /= t2, a /= t3, a /= t4, NoneOf ts a) + NoneOf (t1 ': t2 ': t3 ': ts) a = (a /= t1, a /= t2, a /= t3, NoneOf ts a) + NoneOf (t1 ': t2 ': ts) a = (a /= t1, a /= t2, NoneOf ts a) + NoneOf (t1 ': ts) a = (a /= t1, NoneOf ts a) NoneOf '[] a = () - NoneOf (t ': ts) a = (a /= t, NoneOf ts a)