1. Doug Burke
  2. swish

Commits

Doug Burke  committed 313b306

Uptate to 0.3.1.0; RDFLabel now has IsString instance and added To/FromRDFLabel typeclasses

  • Participants
  • Parent commits 0325e29
  • Branches default

Comments (0)

Files changed (7)

File CHANGES

View file
+0.3.1.0:
+
+  - added IsString instance to RDFLabel
+
+  - added ToRDFLabel and FromRDFLabel type classes for converting
+    to and from RDFLabel along with instances for some standard
+    Haskell types.
+
+    UTCTime support has required adding old-locale and time 
+    to the package constraints.
+
+  - added xsd_dateTime export to Swish.RDF.Vocabulary
+
+0.3.0.3:
+
+  - to be written
+
+0.3.0.2:
+
+  - to be written
+
+0.3.0.1:
+
+  - to be written
+
 0.2.1 to 0.3.0.0:
 
   - Renamed module hierarchy from

File Swish/RDF/RDFGraph.hs

View file
 ------------------------------------------------------------
 
 module Swish.RDF.RDFGraph
-    ( RDFLabel(..)
+    ( RDFLabel(..), ToRDFLabel(..), FromRDFLabel(..)
     , isLiteral, isUntypedLiteral, isTypedLiteral, isXMLLiteral
     , isDatatyped, isMemberProp, isUri, isBlank, isQueryVar
     , getLiteralText, getScopedName, makeBlank
     , rdfd_GeneralRestriction
     , rdfd_onProperties, rdfd_constraint, rdfd_maxCardinality
     , owl_sameAs, log_implies
+    -- , xsd_type
+    , xsd_boolean, xsd_float, xsd_double, xsd_integer
+    , xsd_dateTime                                                
     )
 
 import Swish.RDF.GraphClass
 import Control.Applicative (Applicative, liftA, (<$>), (<*>))
 -- import Control.Monad (liftM, ap)
 
-import Data.Char
-    ( isDigit )
-
-import Data.List
-    ( intersect, union, findIndices )
-
+import Data.Char (isDigit)
+import Data.List (intersect, union, findIndices)
 import Data.Ord (comparing)
+import Data.String (IsString(..))
+import Data.Time (UTCTime, parseTime, formatTime)
+import System.Locale (defaultTimeLocale)  
 
 -----------------------------------------------------------
 -- | RDF graph node values
     makeLabel  loc          = Blank loc
     labelHash seed lb       = hash seed (showCanon lb)
 
+instance IsString RDFLabel where
+  fromString = flip Lit Nothing
+
+-- | A type that can be converted to a RDF Label.
+--
+class ToRDFLabel a where
+  toRDFLabel :: a -> RDFLabel
+  
+-- | A type that can be converted from a RDF Label,
+--   with the possibility of failure.
+--  
+class FromRDFLabel a where
+  fromRDFLabel :: RDFLabel -> Maybe a
+
+-- instances for type conversion to/from RDFLabel
+  
+-- TODO: need to check that the Haskell read/show instances match
+--       the RDF syntactical constraints
+
+maybeRead :: (Read a) => String -> Maybe a
+maybeRead inStr = 
+  case reads inStr of
+    [(val, "")] -> Just val
+    _ -> Nothing
+    
+fLabel :: (String -> Maybe a) -> ScopedName -> RDFLabel -> Maybe a
+fLabel conv dtype (Lit xs (Just dt)) | dt == dtype = conv xs
+                                     | otherwise = Nothing
+fLabel _    _     _ = Nothing
+  
+tLabel :: (Show a) => ScopedName -> a -> RDFLabel                      
+tLabel dtype = flip Lit (Just dtype) . show                      
+
+instance ToRDFLabel Char where
+  toRDFLabel = flip Lit Nothing . (:[])
+
+instance FromRDFLabel Char where
+  fromRDFLabel (Lit [c] Nothing) = Just c
+  fromRDFLabel _ = Nothing
+
+instance ToRDFLabel [Char] where
+  toRDFLabel = flip Lit Nothing
+
+instance FromRDFLabel [Char] where
+  fromRDFLabel (Lit xs Nothing) = Just xs
+  fromRDFLabel _ = Nothing
+
+instance ToRDFLabel Bool where
+  toRDFLabel = tLabel xsd_boolean
+  
+instance FromRDFLabel Bool where
+  fromRDFLabel = fLabel maybeRead xsd_boolean
+
+instance ToRDFLabel Float where
+  toRDFLabel = tLabel xsd_float
+  
+{-
+As reads "<invalid float>" returns some form of Inf
+we need to catch this.
+-}
+
+instance FromRDFLabel Float where
+  fromRDFLabel = fLabel (\istr -> maybeRead istr >>= conv) xsd_float
+    where
+      conv :: Float -> Maybe Float
+      conv i | (isNaN i || isInfinite i || isDenormalized i) = Nothing
+             | otherwise = Just . realToFrac $ i -- or fromRational . toRational
+
+instance ToRDFLabel Double where
+  toRDFLabel = tLabel xsd_double
+  
+instance FromRDFLabel Double where
+  fromRDFLabel = fLabel maybeRead xsd_double
+
+-- TODO: are there subtypes of xsd::integer that are  
+--       useful here?  
+--         
+-- TODO: add in support for Int8/..., Word8/...  
+--  
+instance ToRDFLabel Int where
+  toRDFLabel = tLabel xsd_integer
+
+{-
+it appears that reads doesn't fail when the input is outside
+the Int range; instead it overflows. So instead of
+
+  fromRDFLabel = fLabel maybeRead xsd_integer
+
+we convert via Integer.
+-}
+
+instance FromRDFLabel Int where
+  fromRDFLabel = fLabel (\istr -> maybeRead istr >>= conv) xsd_integer
+    where
+      conv :: Integer -> Maybe Int
+      conv i = 
+        let lb = fromIntegral (minBound :: Int)
+            ub = fromIntegral (maxBound :: Int)
+        in if (i >= lb) && (i <= ub) then Just (fromIntegral i) else Nothing
+
+instance ToRDFLabel Integer where
+  toRDFLabel = tLabel xsd_integer
+
+instance FromRDFLabel Integer where
+  fromRDFLabel = fLabel maybeRead xsd_integer
+
+timeFormat :: String
+timeFormat = "%FT%T%QZ"
+  
+-- TODO: is assumuption of UTC here correct?
+
+{-
+aeson uses
+
+instance ToJSON UTCTime where
+    toJSON t = String (pack (take 23 str ++ "Z"))
+      where str = formatTime defaultTimeLocale "%FT%T%Q" t
+    {-# INLINE toJSON #-}
+
+instance FromJSON UTCTime where
+    parseJSON (String t) =
+        case parseTime defaultTimeLocale "%FT%T%QZ" (unpack t) of
+          Just d -> pure d
+          _      -> fail "could not parse ISO-8601 date"
+    parseJSON v   = typeMismatch "UTCTime" v
+    {-# INLINE parseJSON #-}
+
+-}
+
+instance ToRDFLabel UTCTime where
+  toRDFLabel = flip Lit (Just xsd_dateTime) . 
+            formatTime defaultTimeLocale timeFormat
+  
+instance FromRDFLabel UTCTime where
+  fromRDFLabel = fLabel (parseTime defaultTimeLocale timeFormat) xsd_dateTime
+  
+instance ToRDFLabel ScopedName where  
+  toRDFLabel = Res
+
+instance FromRDFLabel ScopedName where
+  fromRDFLabel (Res sn) = Just sn
+  fromRDFLabel _        = Nothing
+  
+-- TODO: add instance for URI
+
 -- | Get the canonical string for RDF label.
 --
 --  Used for hashing, so that equivalent labels always return

File Swish/RDF/Vocabulary.hs

View file
     , xsd_decimal, xsd_integer
     , xsd_nonneg_integer, xsd_nonpos_integer, xsd_pos_integer, xsd_neg_integer
     , xsd_float, xsd_double
+    , xsd_date, xsd_dateTime
     , default_base
     )
 where
 
-import Swish.Utils.Namespace
-    ( Namespace(..), ScopedName(..) )
-
-import Swish.Utils.MiscHelpers
-    ( lower )
+import Swish.Utils.Namespace (Namespace(..), ScopedName(..))
+import Swish.Utils.MiscHelpers (lower)
 
 ------------------------------------------------------------
 --  Define some common namespace values
 ------------------------------------------------------------
 --
 --  Note:  simple language tag URIs may be abbreviated as lang:tag,
---  but if the tag contains ahyphen, this would not be valid QName
+--  but if the tag contains a hyphen, this would not be valid QName
 --  form in Notation3, even though it is a valid QName component.
 --  Fortunately, they do not currently need to appear in Notation3 as
---  distinct labels (but future developments m,ay change that).
+--  distinct labels (but future developments may change that).
 
 namespaceLang :: Namespace
 namespaceLang
     -- To be replaced by urn:ietf:params:lang?
 
 langName :: String -> ScopedName
-langName tag = ScopedName namespaceLang (lower tag)
+langName = ScopedName namespaceLang . lower
 
 langTag :: ScopedName -> String
 langTag = snLocal
 xsd_double              :: ScopedName
 xsd_double              = xsd_type "double"
 
+xsd_date, xsd_dateTime :: ScopedName
+xsd_date = xsd_type "date"
+xsd_dateTime = xsd_type "dateTime"
+
 owl_sameAs              :: ScopedName
 owl_sameAs              = ScopedName namespaceOWL  "sameAs"
 

File TODO

View file
+
+Some things I want to/should do (not in order)
+
+- use types better - e.g. ScopedName/Namespace has a lot
+  of String entries which could be replaced by Maybe String
+  and URI
+
+- the RDFLabel data type could be split up to add additional
+  type constraints, namely Lit could be split up into something
+  like ULit for an untyped literal, LLit for a language lit
+  coupled with a LString type that combines text and language tag),
+  and DLit for a literal with a datatype. This would require
+  going to 0.4.x
+
+- remove parsec parser, replace by attoparsec-text
+  - use Text rather than String
+  - use attoparsec-text-enumerator?
+
+  This would require going to 0.4.x
+
+- move a lot of parser/formatter tests out to ntriples files
+  (ie the test data in external files).
+
+- turtle parser, then RDF/XML.
+
+- look at using fgl rather than existing graph code (may or
+  may not be worth it), especially given that it's not really a
+  graph
+
+- look at using something like a TextBuilder for processing output
+
+- profile (have added the -fdeveloper cabal flag which can be combined
+  with the --enable-library-profiling and --enable-executable-profiling
+  flags)
+
+- how much of the support code - e.g. Swish.Utils.LookupMap - can now
+  be replaced with packages from hackage? Swish.Utils.DateTime is an
+  obvious candidate.
+
+- add top-level modules - e.g. Swish or Swish.RDF - for documentation and
+  a simple way to load up a useful set of modules.
+

File swish.cabal

View file
 Name:               swish
-Version:            0.3.0.3
+Version:            0.3.1.0
 Stability:          experimental
 License:            LGPL
 License-file:       LICENSE 
 Homepage:           https://bitbucket.org/doug_burke/swish/wiki/Home
 Bug-reports:        https://bitbucket.org/doug_burke/swish/issues
 
-Description:        Swish is a framework, written in the purely functional 
-                    programming language Haskell, for performing deductions in 
-                    RDF data using a variety of techniques. Swish is conceived 
-                    as a toolkit for experimenting with RDF inference, and for 
-                    implementing stand-alone RDF file processors (usable in 
-                    similar style to CWM, but with a view to being extensible 
-                    in declarative style through added Haskell function and data
-                    value declarations). It explores Haskell as \"a scripting 
-                    language for the Semantic Web\".
-                    .
-                    Swish is a work-in-progress, and currently incorporates:
-                    .
-                    * Notation3 and NTriples input and output. The N3 support is
-                      incomplete (no handling of @\@forAll@).
-                    .
-                    * RDF graph isomorphism testing and merging.
-                    .
-                    * Display of differences between RDF graphs.
-                    .
-                    * Inference operations in forward chaining, backward chaining and proof-checking modes.
-                    .
-                    * Simple Horn-style rule implementations, extendable through variable binding modifiers and filters.
-                    .
-                    * Class restriction rule implementation, primarily for datatype inferences.
-                    .
-                    * RDF formal semantics entailment rule implementation.
-                    .
-                    * Complete, ready-to-run, command-line and script-driven programs.
-                    .
-                    Major Changes:
-                    .
-                    [Version 0.3.0.3] Changed @scripts/SwishExample.ss@ script so that the
-                    proof succeeds. Some documentation improvements, including a discussion
-		    of the Swish script format (see "Swish.RDF.SwishScript"). Very minor
-		    changes to behavior of Swish in several edge cases.
-                    .
-                    [Version 0.3.0.2] Bugfix: stop losing triples with a bnode subject when
-                    using the N3Formatter; this also makes the @scripts/SwishTest.ss@ test
-                    pass again. Several commands in Swish scripts now create screen
-                    output (mainly to check what it is doing). Added the @developer@
-		    flag for building.
-                    .
-                    [Version 0.3.0.1] updates the Swish script parser to work with the
-                    changes in 0.3.0.0 (reported by Rick Murphy).
-                    Several example scripts are installed in the
-                    @scripts/@ directory, although only @VehicleCapacity.ss@ works
-                    with this release.
-                    .
-                    [Version 0.3.0.0] is an attempt to update 
-                    version 0.2.1 (<http://hackage.haskell.org/package/swish-0.2.1/>)
-		    to build against
-                    a recent ghc install, with some clean ups - including support for
-                    the current N3 specification - and the addition of the
-                    NTriples format. It has not been tested against ghc7.
-                    .
-                    References:
-                    .
-                      - <http://www.ninebynine.org/RDFNotes/Swish/Intro.html>
-                    .
-                      - <http://www.ninebynine.org/Software/swish-0.2.1.html>
-                    .
-                      - CWM: <http://www.w3.org/2000/10/swap/doc/cwm.html>
-                    .
+Description:        
+  Swish is a framework, written in the purely functional 
+  programming language Haskell, for performing deductions in 
+  RDF data using a variety of techniques. Swish is conceived 
+  as a toolkit for experimenting with RDF inference, and for 
+  implementing stand-alone RDF file processors (usable in 
+  similar style to CWM, but with a view to being extensible 
+  in declarative style through added Haskell function and data
+  value declarations). It explores Haskell as \"a scripting 
+  language for the Semantic Web\".
+  .
+  Swish is a work-in-progress, and currently incorporates:
+  .
+  * Notation3 and NTriples input and output. The N3 support is
+    incomplete (no handling of @\@forAll@).
+  .
+  * RDF graph isomorphism testing and merging.
+  .
+  * Display of differences between RDF graphs.
+  .
+  * Inference operations in forward chaining, backward chaining and proof-checking modes.
+  .
+  * Simple Horn-style rule implementations, extendable through variable binding modifiers and filters.
+  .
+  * Class restriction rule implementation, primarily for datatype inferences.
+  .
+  * RDF formal semantics entailment rule implementation.
+  .
+  * Complete, ready-to-run, command-line and script-driven programs.
+  .
+  Major Changes:
+  .
+  [Version 0.3.1.0] Added the `Swish.RDF.RDFGraph.ToRDFLabel` and
+  `Swish.RDF.RDFGraph.FromRDFLabel` classes to
+  @Swish.RDF.RDFGraph@ and a number of instances for common Haskell
+  datatypes. Added a `Data.String.IsString` instance for
+  `Swish.RDF.RDFGraph.RDFLabel`.
+  .
+  [Version 0.3.0.3] Changed @scripts/SwishExample.ss@ script so that the
+  proof succeeds. Some documentation improvements, including a discussion
+  of the Swish script format (see "Swish.RDF.SwishScript"). Very minor
+  changes to behavior of Swish in several edge cases.
+  .
+  [Version 0.3.0.2] Bugfix: stop losing triples with a bnode subject when
+  using the N3Formatter; this also makes the @scripts/SwishTest.ss@ test
+  pass again. Several commands in Swish scripts now create screen
+  output (mainly to check what it is doing). Added the @developer@
+  flag for building.
+  .
+  [Version 0.3.0.1] updates the Swish script parser to work with the
+  changes in 0.3.0.0 (reported by Rick Murphy).
+  Several example scripts are installed in the
+  @scripts/@ directory, although only @VehicleCapacity.ss@ works
+  with this release.
+  .
+  [Version 0.3.0.0] is an attempt to update 
+  version 0.2.1 (<http://hackage.haskell.org/package/swish-0.2.1/>)
+  to build against
+  a recent ghc install, with some clean ups - including support for
+  the current N3 specification - and the addition of the
+  NTriples format. It has not been tested against ghc7.
+  .
+  References:
+  .
+    - <http://www.ninebynine.org/RDFNotes/Swish/Intro.html>
+  .
+    - <http://www.ninebynine.org/Software/swish-0.2.1.html>
+  .
+    - CWM: <http://www.w3.org/2000/10/swap/doc/cwm.html>
+  .
 
 Build-Type:         Simple
 Data-Files:         README
       parallel == 2.2.*,
       parsec == 2.1.*,
       random == 1.0.*,
-      old-time == 1.0.*,
+      old-time == 1.0.*, old-locale == 1.0.*, time == 1.1.*,
       mtl >= 1 && < 3,
       HUnit == 1.2.*,
       network >= 2.2 && < 2.4,

File tests/N3FormatterTest.hs

View file
 import Swish.RDF.N3Parser (parseN3fromString)
 
 import Swish.RDF.RDFGraph
-    ( RDFGraph, RDFLabel(..), NSGraph(..)
+    ( RDFGraph
+    , RDFLabel(..), ToRDFLabel(..)
+    , NSGraph(..)
     , NamespaceMap
     , LookupFormula(..)
     , emptyRDFGraph, toRDFGraph
     , res_owl_sameAs
     )
 
-import Swish.Utils.Namespace
-    ( Namespace(..)
-    , ScopedName(..)
-    )
+import Swish.Utils.Namespace (Namespace(..), ScopedName(..))
 
 import Swish.Utils.LookupMap
     ( LookupMap(..)
-    , emptyLookupMap, makeLookupMap )
+    , emptyLookupMap, makeLookupMap, mapAdd )
 
 import Swish.RDF.GraphClass (Arc, arc)
 
+import Swish.RDF.Vocabulary (langName)
+
 import Test.HUnit
     ( Test(TestCase,TestList)
     , assertEqual, runTestTT )
 l13 = Lit l13txt Nothing
 l14 = Lit l14txt Nothing
 
+lfr, lfoobar :: RDFLabel
+lfr = Lit "chat et chien" (Just (langName "fr"))
+lfoobar = Lit "foo bar" (Just (ScopedName base1 "o1"))
+  
 f1, f2 :: RDFLabel
 f1 = Res $ ScopedName base1 "f1"
 f2 = Res $ ScopedName base2 "f2"
                        arc b2 p2 o2,
                        arc b3 res_rdf_type o3]
 
+-- datatype/literal graphs
+
+graph_l1, graph_l2, graph_l3 :: RDFGraph
+graph_l1 = toGraph [arc s1 p1 lfr]
+graph_l2 = toGraph [arc s1 p1 lfoobar]
+graph_l3 = 
+  let gtmp = toGraph [arc s1 p1 (toRDFLabel (12::Int)),
+                      arc s1 p1 (toRDFLabel (23.4::Float)),
+                      arc s1 p1 (toRDFLabel ((-2.304e-108)::Double)),
+                      arc s1 p1 (toRDFLabel True)
+                      ]
+  in gtmp { namespaces = mapAdd (namespaces gtmp) (Namespace "xsd" "http://www.w3.org/2001/XMLSchema#") }
+                    
 ------------------------------------------------------------
 --  Trivial formatter tests
 ------------------------------------------------------------
   "[\n base2:p2 base2:o2\n] .\n" ++
   "[\n a base3:o3\n] .\n"
 
+{-
+Simple datatype/language tests; may replicate some of the
+previous tests.
+-}
+simpleN3Graph_l1 :: String
+simpleN3Graph_l1 =
+  commonPrefixes ++
+  "base1:s1 base1:p1 \"chat et chien\"@fr .\n"
+  
+simpleN3Graph_l2 :: String
+simpleN3Graph_l2 =
+  commonPrefixes ++
+  "base1:s1 base1:p1 \"foo bar\"^^base1:o1 .\n"
+  
+simpleN3Graph_l3 :: String
+simpleN3Graph_l3 =
+  "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n" ++ 
+  commonPrefixes ++ 
+  "\n" ++ -- TODO: why do we need this?
+  "base1:s1 base1:p1 \"-2.304e-108\"^^xsd:double,\n" ++ 
+  "                  \"12\"^^xsd:integer,\n" ++ 
+  "                  \"23.4\"^^xsd:float,                  \"True\"^^xsd:boolean .\n"
+  
+{-
+
+-- this is more a parser than formatter test; at the moment we
+-- do not include it.
+
+simpleN3Graph_l3a :: String
+simpleN3Graph_l3a =
+  "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n" ++ 
+  commonPrefixes ++ 
+  "base1:s1 base1:p1 \"12\"^^xsd:integer , \n" ++
+  "  \"23.4\"^^xsd:float \n" ++
+  "  \"-2.304e-108\"^^xsd:double \n" ++
+  "  true .\n"
+  
+-}
+
 -- diag13 = diagTest "trivialTest13" x13a simpleN3Graph_x13a
 
 trivialTestSuite :: Test
  , formatTest "trivialTestb1rev" graph_b1rev simpleN3Graph_b1rev
  , formatTest "trivialTestb2rev" graph_b2rev simpleN3Graph_b2rev
 
+ , formatTest "lit1"   graph_l1   simpleN3Graph_l1  
+ , formatTest "lit2"   graph_l2   simpleN3Graph_l2
+ , formatTest "lit3"   graph_l3   simpleN3Graph_l3
+   
  , formatTest "trivialTestx4" x4 exoticN3Graph_x4
  , formatTest "trivialTestx5" x5 exoticN3Graph_x5
  , formatTest "trivialTestx7" x7 exoticN3Graph_x7
   , roundTripTest "04" g1a1
   , roundTripTest "05" g1l1
   , roundTripTest "06" g1l2
+    
+  , roundTripTest "l1"    graph_l1
+  , roundTripTest "l2"    graph_l2
+  , roundTripTest "l3"    graph_l3
+      
     -- roundTripTest07 = roundTripTest "07" g1f1 -- formula is a named node
   , roundTripTest "08" g1f2
   , fullRoundTripTest "11" simpleN3Graph_g1_01
   , fullRoundTripTest "16rt" simpleN3Graph_g1_06_rt
     -- roundTripTest17 = fullRoundTripTest "17" simpleN3Graph_g1_07 -- TODO: :- with named node for formula
   , fullRoundTripTest "18" simpleN3Graph_g1_08
+  
   ]
 
 ------------------------------------------------------------

File tests/RDFGraphTest.hs

View file
+{-# LANGUAGE OverloadedStrings #-}
+
 --------------------------------------------------------------------------------
 --  See end of this file for licence information.
 --------------------------------------------------------------------------------
     )
 
 import Swish.RDF.RDFGraph
-    ( RDFTriple, RDFGraph, RDFLabel(..), NSGraph(..)
+    ( RDFTriple, 
+      RDFGraph, 
+      RDFLabel(..), ToRDFLabel(..), FromRDFLabel(..),
+      NSGraph(..)
     , isLiteral, isUntypedLiteral, isTypedLiteral, isXMLLiteral
     , isDatatyped, isMemberProp
     , isUri, isBlank, isQueryVar, makeBlank
     , newNode, newNodes )
 
 import Swish.RDF.Vocabulary
-    ( namespaceRDF
-    , langName 
-    , rdf_XMLLiteral
+  ( namespaceRDF
+  , langName 
+  , rdf_XMLLiteral
+  , xsd_boolean
+  , xsd_integer
+  , xsd_float
+  , xsd_double
+  , xsd_dateTime
     )
 
 import qualified Data.Traversable as T
 
-import Data.List
-    ( elemIndex )
+import Data.List (elemIndex)
+import Data.Maybe (fromJust)
 
-import Data.Maybe
-    ( fromJust )
+import System.Locale (defaultTimeLocale)
+import Data.Time (UTCTime, buildTime)
 
 import Test.HUnit
     ( Test(TestCase,TestList,TestLabel)
 es1, us1, s1, s2, s3, s4, s5, s6, s7, s8 :: RDFLabel
 es1 = Res qbes1
 us1 = Res qbus1
-s1 = Res qb1s1 
-s2 = Res qb2s2 
-s3 = Res qb3s3 
+s1 = toRDFLabel qb1s1 
+s2 = toRDFLabel qb2s2 
+s3 = toRDFLabel qb3s3 
 s4 = Res qb3   
 s5 = Blank "s5"
 s6 = Res qb3bm 
 s8 = Blank "s8"
 
 st1, st2, st3 :: RDFLabel
-st1 = Res $ ScopedName base1 "st1"
-st2 = Res $ ScopedName base2 "st2" 
-st3 = Res $ ScopedName base3 "st3"
+st1 = toRDFLabel $ ScopedName base1 "st1"
+st2 = toRDFLabel $ ScopedName base2 "st2" 
+st3 = toRDFLabel $ ScopedName base3 "st3"
 
 bb, bb0, b1, b2, b3, b4, b5, b6, b7,
   b8, b9, b10 :: RDFLabel
 o1 = Res $ ScopedName base1 "o1"
 o2 = Res $ ScopedName base2 "o2"
 o3 = Res $ ScopedName base3 "o3"
-o4 = Res qb3   
+o4 = toRDFLabel qb3   
 o5 = Blank "o5"
 o6 = Blank "s5"
 
 
 l1, l2, l2gb, l3, l4, l5, l6, l7, l8,
   l9, l10, l11, l12 :: RDFLabel
-l1  = Lit "l1"  Nothing                
-l2  = Lit "l2"  (Just (langName "en")) 
+l1   = "l1" -- use IsString instance
+l2   = Lit "l2"  (Just (langName "en")) 
 l2gb = Lit "l2"  (Just (langName "en-gb")) 
-l3  = Lit "l2"  (Just (langName "fr")) 
-l4  = Lit "l4"  (Just qb1t1)           
-l5  = Lit "l4"  (Just qb1t1)           
-l6  = Lit "l4"  (Just qb1t1)           
-l7  = Lit "l4"  (Just qb1t2)           
-l8  = Lit "l4"  (Just qb1t2)           
-l9  = Lit "l4"  (Just qb1t2)           
-l10 = Lit "l10" (Just rdf_XMLLiteral)  
-l11 = Lit "l10" (Just rdf_XMLLiteral)  
-l12 = Lit "l10" (Just rdf_XMLLiteral)  
+l3   = Lit "l2"  (Just (langName "fr")) 
+l4   = Lit "l4"  (Just qb1t1)           
+l5   = Lit "l4"  (Just qb1t1)           
+l6   = Lit "l4"  (Just qb1t1)           
+l7   = Lit "l4"  (Just qb1t2)           
+l8   = Lit "l4"  (Just qb1t2)           
+l9   = Lit "l4"  (Just qb1t2)           
+l10  = Lit "l10" (Just rdf_XMLLiteral)  
+l11  = Lit "l10" (Just rdf_XMLLiteral)  
+l12  = Lit "l10" (Just rdf_XMLLiteral)  
 
 v1, v2, v3, v4, vb3, vb4 :: RDFLabel
 v1  = Var "v1"  
          (ll1,ll2) `elem` nodeeqlist ||
          (ll2,ll1) `elem` nodeeqlist
 
+-- test ToRDFLabel/FromRDFlabel/IsString instances
+--
+    
+testConv :: (ToRDFLabel a, FromRDFLabel a, Eq a, Show a) 
+            => String -> String -> Maybe ScopedName -> a -> Test    
+testConv lbl sVal dtype hVal = 
+  let rdfVal = Lit sVal dtype
+  in TestList
+  [
+    testEq ("tconv:" ++ lbl) rdfVal       (toRDFLabel hVal)
+  , testEq ("fconv:" ++ lbl) (Just hVal)  (fromRDFLabel rdfVal)
+  ]
+    
+testConversionSuite :: Test
+testConversionSuite =
+  TestList
+  [
+    -- failure case
+    testEq "fconv:fail char"    (Nothing :: Maybe Char) (fromRDFLabel l1)
+  , testEq "fconv:fail int1"    (Nothing :: Maybe Int)  (fromRDFLabel l1)
+  , testEq "fconv:fail int2"    (Nothing :: Maybe Int)  (fromRDFLabel (Lit "123456789012345" (Just xsd_integer))) 
+  , testEq "fconv:fail float1"  (Nothing :: Maybe Float)  (fromRDFLabel l1)
+  , testEq "fconv:fail float2"  (Nothing :: Maybe Float)  (fromRDFLabel (Lit "1.234e101" (Just xsd_float))) -- invalid input 
+  , testEq "fconv:fail float2"  (Nothing :: Maybe Float)  (fromRDFLabel (Lit "-1.234e101" (Just xsd_float))) -- invalid input 
+    
+    -- basic string tests
+  , testEq "tconv:emptystring1"  (Lit "" Nothing)    ""       -- want to try out IsString so do not use testConv
+  , testConv "emptystring2"       "" Nothing    (""::String)
+  , testConv "char"                "x" Nothing   'x'
+  , testEq "tconv:l1-1"          (Lit "l1" Nothing)  l1
+  , testConv "l1-2"          "l1" Nothing  ("l1"::String)
+    
+    -- boolean
+  , testConv "True"     "True"    (Just xsd_boolean) True
+  , testConv "False"    "False"   (Just xsd_boolean) False
+    
+    -- numeric types
+  , testConv "int 0"    "0"       (Just xsd_integer) (0::Int)
+  , testConv "int -10"  "-10"     (Just xsd_integer) ((-10)::Int)
+  , testConv "int 10"   "10"      (Just xsd_integer) (10::Int)
+  , testConv "integer 0"    "0"       (Just xsd_integer) (0::Integer)
+  , testConv "integer -10"  "-10"     (Just xsd_integer) ((-10)::Integer)
+  , testConv "integer 10"   "10"      (Just xsd_integer) (10::Integer)
+  , testConv "integer big"  "123456789012345678901234567890"      (Just xsd_integer) (123456789012345678901234567890::Integer)
+  , testConv "integer -big" "-123456789012345678901234567890"     (Just xsd_integer) ((-123456789012345678901234567890)::Integer)
+  , testConv "float 0"        "0.0"     (Just xsd_float) (0::Float)
+  , testConv "float 0.2"      "0.2"     (Just xsd_float) (0.2::Float)
+  , testConv "float -0.2"     "-0.2"    (Just xsd_float) ((-0.2)::Float)
+  , testConv "float 2.01e-4"  "2.01e-4"  (Just xsd_float) (0.000201::Float)
+  , testConv "float -2.01e-4" "-2.01e-4" (Just xsd_float) ((-0.000201)::Float)
+  , testConv "float 2.01e38"  "2.01e38"  (Just xsd_float) (2.01e38::Float)
+  , testConv "float -2.01e38" "-2.01e38" (Just xsd_float) ((-2.01e38)::Float)
+  , testConv "double 0"        "0.0"     (Just xsd_double) (0::Double)
+  , testConv "double 0.2"      "0.2"     (Just xsd_double) (0.2::Double)
+  , testConv "double -0.2"     "-0.2"    (Just xsd_double) ((-0.2)::Double)
+  , testConv "double 2.01e-4"  "2.01e-4"  (Just xsd_double) (0.000201::Double)
+  , testConv "double -2.01e-4" "-2.01e-4" (Just xsd_double) ((-0.000201)::Double)
+  , testConv "double 2.01e38"  "2.01e38"  (Just xsd_double) (2.01e38::Double)
+  , testConv "double -2.01e38" "-2.01e38" (Just xsd_double) ((-2.01e38)::Double)
+  , testConv "double 2.01e108"  "2.01e108"  (Just xsd_double) (2.01e108::Double)
+  , testConv "double -2.01e108" "-2.01e108" (Just xsd_double) ((-2.01e108)::Double)
+  
+    -- URI related types
+  , testEq "tconv:sname s1"    s1             (toRDFLabel qb1s1)
+  , testEq "fconv:sname s1"    (Just qb1s1)   (fromRDFLabel s1)
+    
+    -- time values
+  , testConv "tconv:time1"   "1970-01-01T00:00:00Z"   (Just xsd_dateTime)  utc1
+                              
+    -- TODO
+    
+  ]
+  
+utc1 :: UTCTime
+utc1 = buildTime defaultTimeLocale []
+
 ------------------------------------------------------------
 --  RDFLabel classification tests
 ------------------------------------------------------------
 allTests :: Test
 allTests = TestList
   [ testLangEqSuite
+  , testConversionSuite
   , testNodeEqSuite
   , testNodeClassSuite
   , testNodeLocalSuite