diff --git a/Coco.hs b/Coco.hs
--- a/Coco.hs
+++ b/Coco.hs
@@ -1,14 +1,7 @@
-{-|
-Other conversion packages define isomorphisms and such, but that doesn't guarantee you converting a to b and b to c is the same as converting a to c.
-This package is designed to guarantee conversions are compatible to each other.
-Feel free to request instances.
--}
 module Coco where
-import qualified Language.Haskell.TH as TH
-import Data.Void (Void)
-import Control.Applicative (empty)
-import Control.Monad ((>=>), guard)
 import Data.Either.HT (maybeRight)
+import qualified Data.Vector as Vector
+import Data.Vector (Vector)
 import qualified Data.ByteString.Lazy as B
 import qualified Data.ByteString.Lazy.UTF8 as B
 import qualified Data.ByteString as BS
@@ -19,122 +12,65 @@
 import qualified Data.Text.Encoding as TS
 import Data.UUID (UUID)
 import qualified Data.UUID as UUID
-import qualified Data.Aeson as Aeson
-import qualified Coco.TH
-
-{-|
-Rules:
-
-* Both types must be monomorphic.
-
-* If two of @MaybeTo b a@, @MaybeTo c b@ and @MaybeTo c a@ are defined in your module, the third must be available in (not necessarily defined in) your module.
-
-* For any @a@, @maybeTo a >>= maybeTo@ must be either @maybeTo a@ or @Nothing@.
--}
-class MaybeTo b a where
-	maybeTo :: a -> Maybe b
-	default maybeTo :: To b a => a -> Maybe b
-	maybeTo = pure . to
+import Text.Read (readMaybe)
 
--- | > maybeTo = pure . to
-class MaybeTo b a => To b a where
+-- | convert a to b
+class To b a where
 	to :: a -> b
-	default to :: a ~ b => a -> b
-	to = id
 
 -- | swapped type arguments for convenience
 from :: forall a b. To b a => a -> b
 from = to
 
--- | swapped type arguments for convenience
-maybeFrom :: forall a b. MaybeTo b a => a -> Maybe b
-maybeFrom = maybeTo
-
--- | turn a lossy conversion function into a viable 'maybeTo'
-maybeToViaLossy :: (Eq a, To a b) => (a -> b) -> a -> Maybe b
-maybeToViaLossy f a = f a <$ guard (a == to (f a))
-
--- | reduce boilerplate when defining @To a a@ instances
-instanceId :: Applicative q => [TH.Name] -> q [TH.Dec]
-instanceId = Coco.TH.instance2 ''MaybeTo ''To
-
--- | reduce boilerplate when defining @MaybeTo Void a@ instances
-instanceMaybeToVoid :: Applicative q => [TH.Name] -> q [TH.Dec]
-instanceMaybeToVoid = Coco.TH.instanceMaybeToVoid ''MaybeTo 'maybeTo
-
--- | reduce boilerplate when defining @To a Void@ instances
-instanceFromVoid :: Applicative q => [TH.Name] -> q [TH.Dec]
-instanceFromVoid = Coco.TH.instanceFromVoid ''MaybeTo ''To 'to
-
-$(Coco.TH.instance2 ''To ''MaybeTo (''Void : Coco.TH.nonVoid))
-$(Coco.TH.instanceMaybeToVoid ''MaybeTo 'maybeTo Coco.TH.nonVoid)
-$(Coco.TH.instanceFromVoid ''MaybeTo ''To 'to Coco.TH.nonVoid)
-
-instance To B.ByteString BS.ByteString where to = B.fromStrict
-instance MaybeTo B.ByteString BS.ByteString
-instance To BS.ByteString B.ByteString where to = B.toStrict
-instance MaybeTo BS.ByteString B.ByteString
-
-instance To T.Text TS.Text where to = T.fromStrict
-instance MaybeTo T.Text TS.Text
-instance To TS.Text T.Text where to = T.toStrict
-instance MaybeTo TS.Text T.Text
+instance To a a where
+	to = id
 
+instance To String Word where to = show
+instance To String B.ByteString where to = B.toString
+instance To String BS.ByteString where to = BS.toString
 instance To String T.Text where to = T.unpack
-instance MaybeTo String T.Text
-instance MaybeTo T.Text String where maybeTo = maybeToViaLossy T.pack
 instance To String TS.Text where to = TS.unpack
-instance MaybeTo String TS.Text
-instance MaybeTo TS.Text String where maybeTo = maybeToViaLossy TS.pack
+instance To String UUID where to = UUID.toString
 
+instance To B.ByteString String where to = B.fromString
+instance To B.ByteString BS.ByteString where to = B.fromStrict
 instance To B.ByteString T.Text where to = T.encodeUtf8
-instance MaybeTo B.ByteString T.Text
-instance MaybeTo T.Text B.ByteString where maybeTo = maybeRight . T.decodeUtf8'
-instance To BS.ByteString T.Text where to = to . to @B.ByteString
-instance MaybeTo BS.ByteString T.Text
-instance MaybeTo T.Text BS.ByteString where maybeTo = maybeTo . to @B.ByteString
 instance To B.ByteString TS.Text where to = to . to @T.Text
-instance MaybeTo B.ByteString TS.Text
-instance MaybeTo TS.Text B.ByteString where maybeTo = fmap to . maybeTo @T.Text
-instance To BS.ByteString TS.Text where to = TS.encodeUtf8
-instance MaybeTo BS.ByteString TS.Text
-instance MaybeTo TS.Text BS.ByteString where maybeTo = maybeRight . TS.decodeUtf8'
-instance To B.ByteString String where to = B.fromString
-instance MaybeTo B.ByteString String
-instance MaybeTo String B.ByteString where maybeTo = maybeToViaLossy B.toString
+instance To B.ByteString UUID where to = UUID.toLazyASCIIBytes
+
 instance To BS.ByteString String where to = BS.fromString
-instance MaybeTo BS.ByteString String
-instance MaybeTo String BS.ByteString where maybeTo = maybeToViaLossy BS.toString
+instance To BS.ByteString B.ByteString where to = B.toStrict
+instance To BS.ByteString T.Text where to = to . to @B.ByteString
+instance To BS.ByteString TS.Text where to = TS.encodeUtf8
+instance To BS.ByteString UUID where to = UUID.toASCIIBytes
 
-instance To String UUID where to = UUID.toString
-instance MaybeTo String UUID
-instance MaybeTo UUID String where maybeTo = UUID.fromString
+instance To T.Text Word where to = to . to @String
+instance To T.Text String where to = T.pack
+instance To T.Text TS.Text where to = T.fromStrict
 instance To T.Text UUID where to = to . to @TS.Text
-instance MaybeTo T.Text UUID
+
+instance To TS.Text Word where to = to . to @String
+instance To TS.Text String where to = TS.pack
+instance To TS.Text T.Text where to = T.toStrict
 instance To TS.Text UUID where to = UUID.toText
-instance MaybeTo TS.Text UUID
-instance MaybeTo UUID TS.Text where maybeTo = UUID.fromText
-instance To B.ByteString UUID where to = UUID.toLazyASCIIBytes
-instance MaybeTo B.ByteString UUID
-instance MaybeTo UUID B.ByteString where maybeTo = UUID.fromLazyASCIIBytes
-instance To BS.ByteString UUID where to = UUID.toASCIIBytes
-instance MaybeTo BS.ByteString UUID
-instance MaybeTo UUID BS.ByteString where maybeTo = UUID.fromASCIIBytes
 
-instance To Aeson.Value TS.Text where to = Aeson.String
-instance MaybeTo Aeson.Value TS.Text
-instance MaybeTo TS.Text Aeson.Value where
-	maybeTo (Aeson.String s) = pure s
-	maybeTo _ = empty
-instance To Aeson.Value T.Text where to = to . to @TS.Text
-instance MaybeTo Aeson.Value T.Text
-instance MaybeTo T.Text Aeson.Value where maybeTo = fmap to . maybeTo @TS.Text
-instance MaybeTo Aeson.Value String where maybeTo = fmap to . maybeTo @TS.Text
-instance MaybeTo String Aeson.Value where maybeTo = fmap to . maybeTo @TS.Text
-instance MaybeTo Aeson.Value B.ByteString where maybeTo = fmap to . maybeTo @TS.Text
-instance MaybeTo B.ByteString Aeson.Value where maybeTo = fmap to . maybeTo @TS.Text
-instance MaybeTo Aeson.Value BS.ByteString where maybeTo = fmap to . maybeTo @TS.Text
-instance MaybeTo BS.ByteString Aeson.Value where maybeTo = fmap to . maybeTo @TS.Text
-instance To Aeson.Value UUID where to = to . to @TS.Text
-instance MaybeTo Aeson.Value UUID
-instance MaybeTo UUID Aeson.Value where maybeTo = maybeTo @TS.Text >=> maybeTo
+instance To (Maybe Word) String where to = readMaybe
+instance To (Maybe Word) T.Text where to = to . to @String
+instance To (Maybe Word) TS.Text where to = to . to @String
+
+instance To (Maybe T.Text) B.ByteString where to = maybeRight . T.decodeUtf8'
+instance To (Maybe T.Text) BS.ByteString where to = to . to @B.ByteString
+
+instance To (Maybe TS.Text) B.ByteString where to = fmap to . to @(Maybe T.Text)
+instance To (Maybe TS.Text) BS.ByteString where to = maybeRight . TS.decodeUtf8'
+
+instance To (Maybe UUID) String where to = UUID.fromString
+instance To (Maybe UUID) B.ByteString where to = UUID.fromLazyASCIIBytes
+instance To (Maybe UUID) BS.ByteString where to = UUID.fromASCIIBytes
+instance To (Maybe UUID) T.Text where to = to . to @B.ByteString
+instance To (Maybe UUID) TS.Text where to = UUID.fromText
+
+instance To b a => To [b] (Vector a) where
+	to = fmap to . Vector.toList
+instance To b a => To (Vector b) [a] where
+	to = Vector.fromList . fmap to
diff --git a/Coco/Laws.hs b/Coco/Laws.hs
new file mode 100644
--- /dev/null
+++ b/Coco/Laws.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE UndecidableInstances #-}
+module Coco.Laws where
+import Data.Vector (Vector)
+import qualified Data.ByteString.Lazy as B
+import qualified Data.ByteString as BS
+import qualified Data.Text.Lazy as T
+import qualified Data.Text as TS
+import Coco
+
+-- | > id @a = to . to @b
+class (To b a, To a b) => Is b a
+
+class (Is b a, Is a b) => Iso b a
+instance (Is b a, Is a b) => Iso b a
+
+instance Is String T.Text
+instance Is String TS.Text
+
+instance Is B.ByteString BS.ByteString
+instance Is BS.ByteString B.ByteString
+
+instance Is T.Text TS.Text
+instance Is TS.Text T.Text
+
+instance Is b a => Is [b] (Vector a)
+instance Is b a => Is (Vector b) [a]
diff --git a/Coco/TH.hs b/Coco/TH.hs
deleted file mode 100644
--- a/Coco/TH.hs
+++ /dev/null
@@ -1,63 +0,0 @@
-module Coco.TH where
-import qualified Language.Haskell.TH as TH
-import Data.Void (Void, absurd)
-import Control.Applicative (empty)
-import Control.Monad (join)
-import Data.Foldable1 (Foldable1, foldl1')
-import Data.List.NonEmpty (NonEmpty((:|)))
-import qualified Data.ByteString.Lazy as B
-import qualified Data.ByteString as BS
-import qualified Data.Text.Lazy as T
-import qualified Data.Text as TS
-import Data.UUID (UUID)
-import qualified Data.Aeson as Aeson
-
-instanceD :: (Functor t, Foldable1 t) => [TH.Dec] -> t TH.Name -> TH.Dec
-instanceD = flip
-	$ TH.InstanceD empty empty
-	. foldl1' TH.AppT
-	. fmap TH.ConT
-
-funD :: TH.Name -> TH.Exp -> [TH.Dec]
-funD name
-	= pure
-	. TH.FunD name
-	. pure
-	. flip (TH.Clause empty) empty
-	. TH.NormalB
-
-instance2 :: Applicative q => TH.Name -> TH.Name -> [TH.Name] -> q [TH.Dec]
-instance2 a b
-	= pure
-	. fmap (instanceD empty)
-	. (fmap (:|) [a, b] <*>)
-	. fmap (join (<>) . pure)
-
-instanceMaybeToVoid :: Applicative q => TH.Name -> TH.Name -> [TH.Name] -> q [TH.Dec]
-instanceMaybeToVoid cls fn = pure . fmap
-	( instanceD
-		( funD fn
-		$ TH.AppE (TH.VarE 'pure)
-		$ TH.VarE 'empty
-		)
-	. (cls :|)
-	. (''Void :)
-	. pure
-	)
-
-instanceFromVoid :: Applicative q => TH.Name -> TH.Name -> TH.Name -> [TH.Name] -> q [TH.Dec]
-instanceFromVoid clsMaybeTo clsTo fnTo
-	= pure
-	. (<*>)
-		[ instanceD
-			( funD fnTo
-			$ TH.VarE 'absurd
-			)
-		. (clsTo :|)
-		, instanceD empty
-		. (clsMaybeTo :|)
-		]
-	. fmap (: [''Void])
-
-nonVoid :: [TH.Name]
-nonVoid = [''B.ByteString, ''BS.ByteString, ''T.Text, ''TS.Text, ''String, ''UUID, ''Aeson.Value]
diff --git a/coco.cabal b/coco.cabal
--- a/coco.cabal
+++ b/coco.cabal
@@ -1,14 +1,14 @@
 cabal-version:      3.8
 name:               coco
-version:            0.0.1.0
+version:            1.0.0.0
 build-type:         Simple
 category:           Conversion
 author:             Konrad Czech
 maintainer:         konrad@disroot.org
-synopsis:           compatible conversions
+synopsis:           cozy conversions
 description:
- Other conversion packages define isomorphisms and such, but that doesn't guarantee you converting a to b and b to c is the same as converting a to c.
- This package is designed to guarantee conversions are compatible to each other.
+ A simple conversions library.
+ Laws are optional and separate.
 license:            MIT
 homepage:           https://codeberg.org/czech/coco
 bug-reports:        https://codeberg.org/czech/coco/issues
@@ -19,16 +19,12 @@
 library
  ghc-options: -Wall -Wno-tabs
  default-language: GHC2021
- default-extensions: TemplateHaskell, DefaultSignatures
  build-depends:
-  base >= 4.17 && < 4.23,
-  template-haskell >= 2.19 && < 2.25,
+  base >= 4.16.4.0 && < 4.23,
   utility-ht >= 0.0.16 && < 0.1,
-  bytestring >= 0.11.3 && < 0.13,
+  vector >= 0.12.3.0 && < 0.14,
+  bytestring >= 0.11.4.0 && < 0.13,
   utf8-string >= 1.0.1.1 && < 1.1,
   text >= 1.2.5.0 && < 2.2,
-  uuid >= 1.3.15 && < 1.4,
-  aeson >= 2.1 && < 2.3,
-  foldable1-classes-compat >= 0.1 && < 0.2
- exposed-modules: Coco
- other-modules: Coco.TH
+  uuid >= 1.3.13 && < 1.4,
+ exposed-modules: Coco, Coco.Laws
