packages feed

rank1dynamic 0.1.0.2 → 0.4.3

raw patch · 7 files changed

Files

+ ChangeLog view
@@ -0,0 +1,54 @@+2025-02-04 Laurent P. René de Cotret <laurent.decotret@outlook.com> 0.4.3++* Ported test suite to use `tasty` rather than `test-framework`.+* Removed unused test dependencies (#467)++2024-09-03 Laurent P. René de Cotret <laurent.decotret@outlook.com> 0.4.2++* Bumped dependency bounds to support GHC 8.10.7 - GHC 9.10.1+* Updated links to point to Distributed Haskell monorepo++2020-10-24  Facundo Domínguez  <facundo.dominguez@tweag.io>  0.4.1++* Support ghc-8.6.5 and ghc-8.8.4++2017-08-22  Facundo Domínguez  <facundo.dominguez@tweag.io>  0.4.0++* Add compatibility with ghc-8.2.1.+* Drop support for ghc-7.6 and ghc-7.8.++2016-05-31  Facundo Domínguez  <facundo.dominguez@tweag.io>  0.3.3.0++* Add compatibility with ghc-8.+* Update bug report url in cabal file.++2016-02-18  Facundo Domínguez  <facundo.dominguez@tweag.io>  0.3.2.0++* Stop testing ghc-7.4 and test ghc-7.10.+* Add unsafeToDynamic.++2016-01-25  Facundo Domínguez  <facundo.dominguez@tweag.io>  0.3.1.1++* Push HUnit upper bound.++2015-06-15  Facundo Domínguez  <facundo.dominguez@tweag.io>  0.2.1.0++* Loosen upper bound of ghc-prim.++2014-05-30  Tim Watson  <watson.timothy@gmail.com>  0.2.0.0++* Fix funResultTy so @funResultTy ANY _ = ANY@+* Ensure the result of funResultTy is consistent with unification+* Bump binary version to include 0.7.*++2012-11-22  Edsko de Vries  <edsko@well-typed.com>  0.1.0.2++* Relax package bounds to allow for Binary 0.6++2012-09-27  Edsko de Vries  <edsko@well-typed.com>  0.1.0.1++* Relax lower bound of base to 4.4 (ghc 7.2)++2012-08-10  Edsko de Vries  <edsko@well-typed.com>  0.1.0.0++* Initial release.
LICENSE view
@@ -1,4 +1,5 @@ Copyright (c) 2012, Edsko de Vries+Copyright (c) 2015, Tweag I/O Limited  All rights reserved. 
− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
rank1dynamic.cabal view
@@ -1,28 +1,56 @@+cabal-version:       3.0 Name:                rank1dynamic-Version:             0.1.0.2+Version:             0.4.3 Synopsis:            Like Data.Dynamic/Data.Typeable but with support for rank-1 polymorphic types-Description:         "Data.Typeable" and "Data.Dynamic" only support monomorphic types. +Description:         "Data.Typeable" and "Data.Dynamic" only support monomorphic types.                      In this package we provide similar functionality but with-                     support for rank-1 polymorphic types. -Homepage:            http://github.com/haskell-distributed/distributed-process-License:             BSD3+                     support for rank-1 polymorphic types.+Homepage:            http://haskell-distributed.github.com+License:             BSD-3-Clause License-File:        LICENSE Author:              Edsko de Vries-Maintainer:          edsko@well-typed.com-Copyright:           Well-Typed LLP+maintainer:          The Distributed Haskell team+Bug-Reports:         https://github.com/haskell-distributed/distributed-process/issues+Copyright:           Well-Typed LLP, Tweag I/O Limited Category:            Data Build-Type:          Simple-Cabal-Version:       >=1.8+extra-doc-files: ChangeLog +source-repository head+  Type:     git+  Location: https://github.com/haskell-distributed/distributed-process+  SubDir:   packages/rank1dynamic++common warnings+    ghc-options: -Wall+                 -Wcompat+                 -Widentities+                 -Wincomplete-uni-patterns+                 -Wincomplete-record-updates+                 -Wredundant-constraints+                 -fhide-source-paths+                 -Wpartial-fields+                 -Wunused-packages+ Library+  import:              warnings   Exposed-Modules:     Data.Rank1Dynamic,                        Data.Rank1Typeable-  Build-Depends:       base >= 4.4 && < 4.7,-                       ghc-prim >= 0.2 && < 0.4,-                       binary >= 0.5 && < 0.7 +  Build-Depends:       base >= 4.14 && < 5,+                       binary >= 0.8 && < 0.9   HS-Source-Dirs:      src-  GHC-Options:         -Wall-  Extensions:          EmptyDataDecls,+  default-language:    Haskell2010+  Default-Extensions:  EmptyDataDecls,                        DeriveDataTypeable,-                       ViewPatterns,-                       CPP+                       ViewPatterns++Test-Suite TestRank1Dynamic+  import:            warnings+  Type:              exitcode-stdio-1.0+  Main-Is:           test.hs+  Build-Depends:     base >= 4.14 && < 5,+                     rank1dynamic,+                     tasty >= 1.5 && <1.6,+                     tasty-hunit >=0.10 && <0.11,+  default-language:  Haskell2010+  HS-Source-Dirs:    tests
src/Data/Rank1Dynamic.hs view
@@ -5,42 +5,42 @@ -- These examples correspond to the 'Data.Rank1Typeable.isInstanceOf' examples -- in "Data.Rank1Typeable". ----- > > do f <- fromDynamic (toDynamic (even :: Int -> Bool)) ; return $ (f :: Int -> Int) 0 +-- > > do f <- fromDynamic (toDynamic (even :: Int -> Bool)) ; return $ (f :: Int -> Int) 0 -- > Left "Cannot unify Int and Bool"--- > +-- > -- > > do f <- fromDynamic (toDynamic (const 1 :: ANY -> Int)) ; return $ (f :: Int -> Int) 0 -- > Right 1--- > +-- > -- > > do f <- fromDynamic (toDynamic (unsafeCoerce :: ANY1 -> ANY2)) ; return $ (f :: Int -> Int) 0 -- > Right 0--- > +-- > -- > > do f <- fromDynamic (toDynamic (id :: ANY -> ANY)) ; return $ (f :: Int -> Bool) 0 -- > Left "Cannot unify Bool and Int"--- > +-- > -- > > do f <- fromDynamic (toDynamic (undefined :: ANY)) ; return $ (f :: Int -> Int) 0 -- > Right *** Exception: Prelude.undefined--- > +-- > -- > > do f <- fromDynamic (toDynamic (id :: ANY -> ANY)) ; return $ (f :: Int) -- > Left "Cannot unify Int and ->" -- -- [Examples of dynApply]--- +-- -- These examples correspond to the 'Data.Rank1Typeable.funResultTy' examples -- in "Data.Rank1Typeable". -- -- > > do app <- toDynamic (id :: ANY -> ANY) `dynApply` toDynamic True ; f <- fromDynamic app ; return $ (f :: Bool) -- > Right True--- > +-- > -- > > do app <- toDynamic (const :: ANY -> ANY1 -> ANY) `dynApply` toDynamic True ; f <- fromDynamic app ; return $ (f :: Int -> Bool) 0 -- > Right True--- > +-- > -- > > do app <- toDynamic (($ True) :: (Bool -> ANY) -> ANY) `dynApply` toDynamic (id :: ANY -> ANY) ; f <- fromDynamic app ; return (f :: Bool) -- > Right True--- > +-- > -- > > app <- toDynamic (const :: ANY -> ANY1 -> ANY) `dynApply` toDynamic (id :: ANY -> ANY) ; f <- fromDynamic app ; return $ (f :: Int -> Bool -> Bool) 0 True -- > Right True--- > --- > > do app <- toDynamic ((\f -> f . f) :: (ANY -> ANY) -> ANY -> ANY) `dynApply` toDynamic (even :: Int -> Bool) ; f <- fromDynamic app ; return (f :: ()) +-- >+-- > > do app <- toDynamic ((\f -> f . f) :: (ANY -> ANY) -> ANY -> ANY) `dynApply` toDynamic (even :: Int -> Bool) ; f <- fromDynamic app ; return (f :: ()) -- > Left "Cannot unify Int and Bool" -- -- [Using toDynamic]@@ -48,40 +48,41 @@ -- When using polymorphic values you need to give an explicit type annotation: -- -- > > toDynamic id--- > +-- > -- > <interactive>:46:1: -- >     Ambiguous type variable `a0' in the constraint: -- >       (Typeable a0) arising from a use of `toDynamic' -- >     Probable fix: add a type signature that fixes these type variable(s) -- >     In the expression: toDynamic id -- >     In an equation for `it': it = toDynamic id--- +-- -- versus -- -- > > toDynamic (id :: ANY -> ANY) -- > <<ANY -> ANY>>--- +-- -- Note that these type annotation are checked by ghc like any other: -- -- > > toDynamic (id :: ANY -> ANY1)--- > +-- > -- > <interactive>:45:12: -- >     Couldn't match expected type `V1' with actual type `V0' -- >     Expected type: ANY -> ANY1 -- >       Actual type: ANY -> ANY -- >     In the first argument of `toDynamic', namely `(id :: ANY -> ANY1)' -- >     In the expression: toDynamic (id :: ANY -> ANY1)-module Data.Rank1Dynamic +module Data.Rank1Dynamic   ( Dynamic   , toDynamic   , fromDynamic   , TypeError   , dynTypeRep   , dynApply+  , unsafeToDynamic   ) where -import qualified GHC.Prim as GHC (Any)-import Data.Rank1Typeable +import qualified GHC.Exts as GHC (Any)+import Data.Rank1Typeable   ( Typeable   , TypeRep   , typeOf@@ -95,16 +96,25 @@ data Dynamic = Dynamic TypeRep GHC.Any  instance Show Dynamic where-  showsPrec _ (Dynamic t _) = showString "<<" . shows t . showString ">>" +  showsPrec _ (Dynamic t _) = showString "<<" . shows t . showString ">>" --- | Introduce a dynamic value +-- | Introduce a dynamic value toDynamic :: Typeable a => a -> Dynamic toDynamic x = Dynamic (typeOf x) (unsafeCoerce x) +-- | Construct a dynamic value with a user-supplied type rep+--+-- This function is unsafe because we have no way of verifying that the+-- provided type representation matches the value.+--+-- Since 0.3.2.0.+unsafeToDynamic :: TypeRep -> a -> Dynamic+unsafeToDynamic typ x = Dynamic typ (unsafeCoerce x)+ -- | Eliminate a dynamic value fromDynamic :: Typeable a => Dynamic -> Either TypeError a fromDynamic (Dynamic t v) =-  case unsafeCoerce v of +  case unsafeCoerce v of     r -> case typeOf r `isInstanceOf` t of       Left err -> Left err       Right () -> Right r
src/Data/Rank1Typeable.hs view
@@ -1,7 +1,7 @@ -- | Runtime type representation of terms with support for rank-1 polymorphic -- types with type variables of kind *. ----- The essence of this module is that we use the standard 'Typeable' +-- The essence of this module is that we use the standard 'Typeable' -- representation of "Data.Typeable" but we introduce a special (empty) data -- type 'TypVar' which represents type variables. 'TypVar' is indexed by an -- arbitrary other data type, giving you an unbounded number of type variables;@@ -12,23 +12,23 @@ -- > -- We CANNOT use a term of type 'Int -> Bool' as 'Int -> Int' -- > > typeOf (undefined :: Int -> Int) `isInstanceOf` typeOf (undefined :: Int -> Bool) -- > Left "Cannot unify Int and Bool"--- > +-- > -- > -- We CAN use a term of type 'forall a. a -> Int' as 'Int -> Int' -- > > typeOf (undefined :: Int -> Int) `isInstanceOf` typeOf (undefined :: ANY -> Int) -- > Right ()--- > +-- > -- > -- We CAN use a term of type 'forall a b. a -> b' as 'forall a. a -> a' -- > > typeOf (undefined :: ANY -> ANY) `isInstanceOf` typeOf (undefined :: ANY -> ANY1) -- > Right ()--- > +-- > -- > -- We CANNOT use a term of type 'forall a. a -> a' as 'forall a b. a -> b' -- > > typeOf (undefined :: ANY -> ANY1) `isInstanceOf` typeOf (undefined :: ANY -> ANY) -- > Left "Cannot unify Succ and Zero"--- > +-- > -- > -- We CAN use a term of type 'forall a. a' as 'forall a. a -> a' -- > > typeOf (undefined :: ANY -> ANY) `isInstanceOf` typeOf (undefined :: ANY) -- > Right ()--- > +-- > -- > -- We CANNOT use a term of type 'forall a. a -> a' as 'forall a. a' -- > > typeOf (undefined :: ANY) `isInstanceOf` typeOf (undefined :: ANY -> ANY) -- > Left "Cannot unify Skolem and ->"@@ -37,14 +37,14 @@ -- -- [Examples of funResultTy] ----- > -- Apply fn of type (forall a. a -> a) to arg of type Bool gives Bool +-- > -- Apply fn of type (forall a. a -> a) to arg of type Bool gives Bool -- > > funResultTy (typeOf (undefined :: ANY -> ANY)) (typeOf (undefined :: Bool)) -- > Right Bool--- > +-- > -- > -- Apply fn of type (forall a b. a -> b -> a) to arg of type Bool gives forall a. a -> Bool -- > > funResultTy (typeOf (undefined :: ANY -> ANY1 -> ANY)) (typeOf (undefined :: Bool)) -- > Right (ANY -> Bool) -- forall a. a -> Bool--- > +-- > -- > -- Apply fn of type (forall a. (Bool -> a) -> a) to argument of type (forall a. a -> a) gives Bool -- > > funResultTy (typeOf (undefined :: (Bool -> ANY) -> ANY)) (typeOf (undefined :: ANY -> ANY)) -- > Right Bool@@ -56,14 +56,14 @@ -- > -- Cannot apply function of type (forall a. (a -> a) -> a -> a) to arg of type (Int -> Bool) -- > > funResultTy (typeOf (undefined :: (ANY -> ANY) -> (ANY -> ANY))) (typeOf (undefined :: Int -> Bool)) -- > Left "Cannot unify Int and Bool"-module Data.Rank1Typeable -  ( -- * Basic types +{-# LANGUAGE BangPatterns #-}+module Data.Rank1Typeable+  ( -- * Basic types     TypeRep   , typeOf   , splitTyConApp   , mkTyConApp-  , underlyingTypeRep-    -- * Operations on type representations +    -- * Operations on type representations   , isInstanceOf   , funResultTy   , TypeError@@ -98,65 +98,86 @@ import Prelude hiding (succ) import Control.Arrow ((***), second) import Control.Monad (void)-import Control.Applicative ((<$>))+import Data.Binary+import Data.Function (on) import Data.List (intersperse, isPrefixOf) import Data.Maybe (fromMaybe)-import Data.Typeable (Typeable, mkTyCon3)-import Data.Typeable.Internal (listTc, funTc, TyCon(TyCon), tyConName)-import Data.Binary (Binary(get, put))-import GHC.Fingerprint.Type (Fingerprint(..))-import qualified Data.Typeable as Typeable -  ( TypeRep-  , typeOf-  , splitTyConApp-  , mkTyConApp-  )+import Data.Typeable ( Typeable )+import qualified Data.Typeable as T+import GHC.Fingerprint +tcList, tcFun :: TyCon+tcList = fst $ splitTyConApp $ typeOf [()]+tcFun = fst $ splitTyConApp $ typeOf (\() -> ())+ -------------------------------------------------------------------------------- -- The basic type                                                             -- --------------------------------------------------------------------------------  -- | Dynamic type representation with support for rank-1 types-newtype TypeRep = TypeRep { -    -- | Return the underlying standard ("Data.Typeable") type representation-    underlyingTypeRep :: Typeable.TypeRep -  }+data TypeRep+    = TRCon TyCon+    | TRApp {-# UNPACK #-} !Fingerprint TypeRep TypeRep +data TyCon = TyCon+    { tyConFingerprint :: {-# UNPACK #-} !Fingerprint+    , tyConPackage :: String+    , tyConModule :: String+    , tyConName :: String+    }++-- | The fingerprint of a TypeRep+typeRepFingerprint :: TypeRep -> Fingerprint+typeRepFingerprint (TRCon c) = tyConFingerprint c+typeRepFingerprint (TRApp fp _ _) = fp+ -- | Compare two type representations------ For base >= 4.6 this compares fingerprints, but older versions of base--- have a bug in the fingerprint construction --- (<http://hackage.haskell.org/trac/ghc/ticket/5962>)+instance Eq TyCon where+  (==) = (==) `on` tyConFingerprint+ instance Eq TypeRep where-#if ! MIN_VERSION_base(4,6,0)-  (splitTyConApp -> (c1, ts1)) == (splitTyConApp -> (c2, ts2)) =-    c1 == c2 && all (uncurry (==)) (zip ts1 ts2)-#else-  t1 == t2 = underlyingTypeRep t1 == underlyingTypeRep t2-#endif+  (==) = (==) `on` typeRepFingerprint --- Binary instance for 'TypeRep', avoiding orphan instances+--- Binary instance for 'TypeRep', avoiding orphan instances instance Binary TypeRep where-  put (splitTyConApp -> (TyCon (Fingerprint hi lo) package modul name, ts)) = do-    put hi -    put lo-    put package-    put modul-    put name+  put (splitTyConApp -> (tc, ts)) = do+    put $ tyConPackage tc+    put $ tyConModule tc+    put $ tyConName tc     put ts   get = do-    hi      <- get-    lo      <- get     package <- get     modul   <- get     name    <- get     ts      <- get-    return $ mkTyConApp (TyCon (Fingerprint hi lo) package modul name) ts+    return $ mkTyConApp (mkTyCon3 package modul name) ts  -- | The type representation of any 'Typeable' term typeOf :: Typeable a => a -> TypeRep-typeOf = TypeRep . Typeable.typeOf+typeOf = trTypeOf . T.typeOf +-- | Conversion from Data.Typeable.TypeRep to Data.Rank1Typeable.TypeRep+trTypeOf :: T.TypeRep -> TypeRep+trTypeOf t = let (c, ts) = T.splitTyConApp t+              in foldl mkTRApp (TRCon $ fromTypeableTyCon c) $ map trTypeOf ts+  where+    fromTypeableTyCon c =+      TyCon (T.tyConFingerprint c)+            (T.tyConPackage c)+            (T.tyConModule c)+            (T.tyConName c)++-- | Applies a TypeRep to another.+mkTRApp :: TypeRep -> TypeRep -> TypeRep+mkTRApp t0 t1 = TRApp fp t0 t1+  where+    fp = fingerprintFingerprints [typeRepFingerprint t0, typeRepFingerprint t1]++mkTyCon3 :: String -> String -> String -> TyCon+mkTyCon3 pkg m name = TyCon fp pkg m name+  where+    fp = fingerprintFingerprints [ fingerprintString s | s <- [pkg, m, name] ]+ -------------------------------------------------------------------------------- -- Constructors/destructors (views)                                           -- --------------------------------------------------------------------------------@@ -164,16 +185,16 @@ -- | Split a type representation into the application of -- a type constructor and its argument splitTyConApp :: TypeRep -> (TyCon, [TypeRep])-splitTyConApp t = -  let (c, ts) = Typeable.splitTyConApp (underlyingTypeRep t)-  in (c, map TypeRep ts)+splitTyConApp = go []+  where+    go xs (TRCon c) = (c, xs)+    go xs (TRApp _ t0 t1) = go (t1 : xs) t0  -- | Inverse of 'splitTyConApp' mkTyConApp :: TyCon -> [TypeRep] -> TypeRep-mkTyConApp c ts -  = TypeRep (Typeable.mkTyConApp c (map underlyingTypeRep ts))+mkTyConApp c = foldl mkTRApp (TRCon c) -isTypVar :: TypeRep -> Maybe Var +isTypVar :: TypeRep -> Maybe Var isTypVar (splitTyConApp -> (c, [t])) | c == typVar = Just t isTypVar _ = Nothing @@ -190,7 +211,7 @@ -- Type variables                                                             -- -------------------------------------------------------------------------------- -data TypVar a deriving Typeable +data TypVar a deriving Typeable data Skolem a deriving Typeable data Zero     deriving Typeable data Succ a   deriving Typeable@@ -206,7 +227,7 @@ type V8 = Succ V7 type V9 = Succ V8 -type ANY  = TypVar V0 +type ANY  = TypVar V0 type ANY1 = TypVar V1 type ANY2 = TypVar V2 type ANY3 = TypVar V3@@ -224,18 +245,17 @@ -- | If 'isInstanceOf' fails it returns a type error type TypeError = String --- | @t1 `isInstanceOf` t2@ checks if @t1@ is an instance of @t2@ -isInstanceOf :: TypeRep -> TypeRep -> Either TypeError () +-- | @t1 `isInstanceOf` t2@ checks if @t1@ is an instance of @t2@+isInstanceOf :: TypeRep -> TypeRep -> Either TypeError () isInstanceOf t1 t2 = void (unify (skolemize t1) t2)  -- | @funResultTy t1 t2@ is the type of the result when applying a function -- of type @t1@ to an argument of type @t2@-funResultTy :: TypeRep -> TypeRep -> Either TypeError TypeRep -funResultTy (splitTyConApp -> (fc, [farg, fres])) x | fc == funTc = do -  s <- unify (alphaRename "f" farg) (alphaRename "x" x)-  return (normalize (subst s (alphaRename "f" fres)))-funResultTy f _ =  -  Left $ show f ++ " is not a function"+funResultTy :: TypeRep -> TypeRep -> Either TypeError TypeRep+funResultTy t1 t2 = do+  let anyTy = mkTypVar $ typeOf (undefined :: V0)+  s <- unify (alphaRename "f" t1) $ mkTyConApp tcFun [alphaRename "x" t2, anyTy]+  return $ normalize $ subst s anyTy  -------------------------------------------------------------------------------- -- Alpha-renaming and normalization                                           --@@ -251,7 +271,7 @@ tvars (isTypVar -> Just x)       = [x] tvars (splitTyConApp -> (_, ts)) = concatMap tvars ts -normalize :: TypeRep -> TypeRep +normalize :: TypeRep -> TypeRep normalize t = subst (zip (tvars t) anys) t   where     anys :: [TypeRep]@@ -261,7 +281,7 @@     succ = mkTyConApp succTyCon . (:[])      zero :: TypeRep-    zero = mkTyConApp zeroTyCon [] +    zero = mkTyConApp zeroTyCon []  mkTyCon :: String -> TyCon mkTyCon = mkTyCon3 "rank1typeable" "Data.Rank1Typeable"@@ -281,38 +301,38 @@ type Var          = TypeRep  skolemize :: TypeRep -> TypeRep-skolemize (isTypVar -> Just x)       = mkTyConApp skolem [x] +skolemize (isTypVar -> Just x)       = mkTyConApp skolem [x] skolemize (splitTyConApp -> (c, ts)) = mkTyConApp c (map skolemize ts)  occurs :: Var -> TypeRep -> Bool-occurs x (isTypVar -> Just x')      = x == x' +occurs x (isTypVar -> Just x')      = x == x' occurs x (splitTyConApp -> (_, ts)) = any (occurs x) ts  subst :: Substitution -> TypeRep -> TypeRep subst s (isTypVar -> Just x)       = fromMaybe (mkTypVar x) (lookup x s) subst s (splitTyConApp -> (c, ts)) = mkTyConApp c (map (subst s) ts) -unify :: TypeRep -      -> TypeRep -      -> Either TypeError Substitution +unify :: TypeRep+      -> TypeRep+      -> Either TypeError Substitution unify = \t1 t2 -> go [] [(t1, t2)]   where-    go :: Substitution -       -> [Equation] -       -> Either TypeError Substitution -    go acc [] = +    go :: Substitution+       -> [Equation]+       -> Either TypeError Substitution+    go acc [] =       return acc     go acc ((t1, t2) : eqs) | t1 == t2 = -- Note: equality check is fast       go acc eqs     go acc ((isTypVar -> Just x, t) : eqs) =-      if x `occurs` t +      if x `occurs` t         then Left "Occurs check"-        else go ((x, t) : map (second $ subst [(x, t)]) acc) +        else go ((x, t) : map (second $ subst [(x, t)]) acc)                 (map (subst [(x, t)] *** subst [(x, t)]) eqs)     go acc ((t, isTypVar -> Just x) : eqs) =       go acc ((mkTypVar x, t) : eqs)-    go acc ((splitTyConApp -> (c1, ts1), splitTyConApp -> (c2, ts2)) : eqs) = -      if c1 /= c2 +    go acc ((splitTyConApp -> (c1, ts1), splitTyConApp -> (c2, ts2)) : eqs) =+      if c1 /= c2         then Left $ "Cannot unify " ++ show c1 ++ " and " ++ show c2         else go acc (zip ts1 ts2 ++ eqs) @@ -320,18 +340,21 @@ -- Pretty-printing                                                            -- -------------------------------------------------------------------------------- +instance Show TyCon where+  showsPrec _ c = showString (tyConName c)+ instance Show TypeRep where   showsPrec p (splitTyConApp -> (tycon, tys)) =       case tys of         [] -> showsPrec p tycon-        [anyIdx -> Just i] | tycon == typVar -> showString "ANY" . showIdx i -        [x] | tycon == listTc -> +        [anyIdx -> Just i] | tycon == typVar -> showString "ANY" . showIdx i+        [x] | tycon == tcList ->           showChar '[' . shows x . showChar ']'-        [a,r] | tycon == funTc -> -          showParen (p > 8) $ showsPrec 9 a -                            . showString " -> " +        [a,r] | tycon == tcFun ->+          showParen (p > 8) $ showsPrec 9 a+                            . showString " -> "                             . showsPrec 8 r-        xs | isTupleTyCon tycon -> +        xs | isTupleTyCon tycon ->           showTuple xs         _ ->           showParen (p > 9) $ showsPrec p tycon@@ -344,16 +367,16 @@ showArgs :: Show a => [a] -> ShowS showArgs [] = id showArgs [a] = showsPrec 10 a-showArgs (a:as) = showsPrec 10 a . showString " " . showArgs as +showArgs (a:as) = showsPrec 10 a . showString " " . showArgs as -anyIdx :: TypeRep -> Maybe Int +anyIdx :: TypeRep -> Maybe Int anyIdx (splitTyConApp -> (c, []))  | c == zeroTyCon = Just 0 anyIdx (splitTyConApp -> (c, [t])) | c == succTyCon = (+1) <$> anyIdx t anyIdx _ = Nothing  showTuple :: [TypeRep] -> ShowS showTuple args = showChar '('-               . foldr (.) id ( intersperse (showChar ',') +               . foldr (.) id ( intersperse (showChar ',')                               $ map (showsPrec 10) args                               )                . showChar ')'
+ tests/test.hs view
@@ -0,0 +1,133 @@+{-# LANGUAGE CPP #-}+import           Data.Rank1Dynamic+import           Data.Rank1Typeable++import           Test.Tasty+import           Test.Tasty.HUnit+import           Unsafe.Coerce++funKindStr :: String+#if defined(MIN_VERSION_GLASGOW_HASKELL) && MIN_VERSION_GLASGOW_HASKELL(9,0,0,0)+funKindStr = "FUN"+#elif __GLASGOW_HASKELL__ >= 804+funKindStr = "->"+#else+funKindStr = "(->)"+#endif+++main :: IO ()+main = defaultMain (testGroup "rank1dynamic" tests)++tests :: [TestTree]+tests =+  [ testGroup "Examples of isInstanceOf"+      [ testCase "CANNOT use a term of type 'Int -> Bool' as 'Int -> Int'" $+          typeOf (undefined :: Int -> Int) `isInstanceOf` typeOf (undefined :: Int -> Bool)+          @?= Left "Cannot unify Int and Bool"++      , testCase "CAN use a term of type 'forall a. a -> Int' as 'Int -> Int'" $+          typeOf (undefined :: Int -> Int) `isInstanceOf` typeOf (undefined :: ANY -> Int)+          @?= Right ()++      , testCase "CAN use a term of type 'forall a b. a -> b' as 'forall a. a -> a'" $+          typeOf (undefined :: ANY -> ANY) `isInstanceOf` typeOf (undefined :: ANY -> ANY1)+          @?= Right ()++      , testCase "CANNOT use a term of type 'forall a. a -> a' as 'forall a b. a -> b'" $+          typeOf (undefined :: ANY -> ANY1) `isInstanceOf` typeOf (undefined :: ANY -> ANY)+          @?= Left "Cannot unify Succ and Zero"++      , testCase "CAN use a term of type 'forall a. a' as 'forall a. a -> a'" $+          typeOf (undefined :: ANY -> ANY) `isInstanceOf` typeOf (undefined :: ANY)+          @?= Right ()++      , testCase "CANNOT use a term of type 'forall a. a -> a' as 'forall a. a'" $+          typeOf (undefined :: ANY) `isInstanceOf` typeOf (undefined :: ANY -> ANY)+          @?= Left ("Cannot unify Skolem and " ++ funKindStr)+      ]++  , testGroup "Examples of funResultTy"+      [ testCase "Apply fn of type (forall a. a -> a) to arg of type Bool gives Bool" $+          show (funResultTy (typeOf (undefined :: ANY -> ANY)) (typeOf (undefined :: Bool)))+          @?= "Right Bool"++      , testCase "Apply fn of type (forall a b. a -> b -> a) to arg of type Bool gives forall a. a -> Bool" $+          show (funResultTy (typeOf (undefined :: ANY -> ANY1 -> ANY)) (typeOf (undefined :: Bool)))+          @?= "Right (ANY -> Bool)" -- forall a. a -> Bool++      , testCase "Apply fn of type (forall a. (Bool -> a) -> a) to argument of type (forall a. a -> a) gives Bool" $+          show (funResultTy (typeOf (undefined :: (Bool -> ANY) -> ANY)) (typeOf (undefined :: ANY -> ANY)))+          @?= "Right Bool"++      , testCase "Apply fn of type (forall a b. a -> b -> a) to arg of type (forall a. a -> a) gives (forall a b. a -> b -> b)" $+        show (funResultTy (typeOf (undefined :: ANY -> ANY1 -> ANY)) (typeOf (undefined :: ANY1 -> ANY1)))+        @?= "Right (ANY -> ANY1 -> ANY1)"++      , testCase "Cannot apply function of type (forall a. (a -> a) -> a -> a) to arg of type (Int -> Bool)" $+          show (funResultTy (typeOf (undefined :: (ANY -> ANY) -> (ANY -> ANY))) (typeOf (undefined :: Int -> Bool)))+          @?= "Left \"Cannot unify Int and Bool\""+      ]++  , testGroup "Examples of fromDynamic"+      [ testCase "CANNOT use a term of type 'Int -> Bool' as 'Int -> Int'" $+          do f <- fromDynamic (toDynamic (even :: Int -> Bool))+             return $ (f :: Int -> Int) 0+          @?= Left "Cannot unify Int and Bool"++      , testCase "CAN use a term of type 'forall a. a -> Int' as 'Int -> Int'" $+          do f <- fromDynamic (toDynamic (const 1 :: ANY -> Int))+             return $ (f :: Int -> Int) 0+          @?= Right 1++      , testCase "CAN use a term of type 'forall a b. a -> b' as 'forall a. a -> a'" $+          do f <- fromDynamic (toDynamic (unsafeCoerce :: ANY1 -> ANY2))+             return $ (f :: Int -> Int) 0+          @?= Right 0++      , testCase "CANNOT use a term of type 'forall a. a -> a' as 'forall a b. a -> b'" $+          do f <- fromDynamic (toDynamic (id :: ANY -> ANY))+             return $ (f :: Int -> Bool) 0+          @?= Left "Cannot unify Bool and Int"++      , testCase "CAN use a term of type 'forall a. a' as 'forall a. a -> a'" $+          case do f <- fromDynamic (toDynamic (undefined :: ANY))+                  return $ (f :: Int -> Int) 0+               of+            Right _ -> return ()+            result  -> assertFailure $ "Expected 'Right _' but got '" ++ show result ++ "'"++      , testCase "CANNOT use a term of type 'forall a. a -> a' as 'forall a. a'" $+          do f <- fromDynamic (toDynamic (id :: ANY -> ANY)) ; return $ (f :: Int)+          @?= Left ("Cannot unify Int and " ++ funKindStr)+      ]++  , testGroup "Examples of dynApply"+      [ testCase "Apply fn of type (forall a. a -> a) to arg of type Bool gives Bool" $+          do app <- toDynamic (id :: ANY -> ANY) `dynApply` toDynamic True+             f <- fromDynamic app+             return $ (f :: Bool)+          @?= Right True++      , testCase "Apply fn of type (forall a b. a -> b -> a) to arg of type Bool gives forall a. a -> Bool" $+          do app <- toDynamic (const :: ANY -> ANY1 -> ANY) `dynApply` toDynamic True+             f <- fromDynamic app+             return $ (f :: Int -> Bool) 0+          @?= Right True++      , testCase "Apply fn of type (forall a. (Bool -> a) -> a) to argument of type (forall a. a -> a) gives Bool" $+          do app <- toDynamic (($ True) :: (Bool -> ANY) -> ANY) `dynApply` toDynamic (id :: ANY -> ANY)+             f <- fromDynamic app+             return (f :: Bool)+          @?= Right True++      , testCase "Apply fn of type (forall a b. a -> b -> a) to arg of type (forall a. a -> a) gives (forall a b. a -> b -> b)" $+          do app <- toDynamic (const :: ANY -> ANY1 -> ANY) `dynApply` toDynamic (id :: ANY -> ANY)+             f <- fromDynamic app ; return $ (f :: Int -> Bool -> Bool) 0 True+          @?= Right True++      , testCase "Cannot apply function of type (forall a. (a -> a) -> a -> a) to arg of type (Int -> Bool)" $+          do app <- toDynamic ((\f -> f . f) :: (ANY -> ANY) -> ANY -> ANY) `dynApply` toDynamic (even :: Int -> Bool) ; f <- fromDynamic app ; return (f :: ())+          @?= Left "Cannot unify Int and Bool"+      ]+  ]