diff --git a/.travis.yml b/.travis.yml
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,12 +3,13 @@
 env:
  - GHCVER=7.6.3
  - GHCVER=7.8.3 # see note about Alex/Happy
+ - GHCVER=7.10.1 # see note about Alex/Happy
 
 before_install:
  - travis_retry sudo add-apt-repository -y ppa:hvr/ghc
  - travis_retry sudo apt-get update
- - travis_retry sudo apt-get install cabal-install-1.18 ghc-$GHCVER libgsl0-dev liblapack-dev
- - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/1.18/bin:$PATH
+ - travis_retry sudo apt-get install cabal-install-1.22 ghc-$GHCVER libgsl0-dev liblapack-dev
+ - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/1.22/bin:$PATH
 
 install:
  - cabal update
@@ -23,7 +24,7 @@
  - cabal sdist   # tests that a source-distribution can be generated
 
 # The following scriptlet checks that the resulting source distribution can be built & installed
- - export SRC_TGZ=$(cabal-1.18 info . | awk '{print $2 ".tar.gz";exit}') ;
+ - export SRC_TGZ=$(cabal-1.22 info . | awk '{print $2 ".tar.gz";exit}') ;
    cd dist/;
    if [ -f "$SRC_TGZ" ]; then
       cabal install "$SRC_TGZ";
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 generic-accessors
 ==
 
-[![Build Status](https://travis-ci.org/ghorn/generic-accessors.png?branch=master)](https://travis-ci.org/ghorn/generic-accessors)
+[![Hackage](https://img.shields.io/hackage/v/generic-accessors.svg)](https://hackage.haskell.org/package/generic-accessors) [![Build Status](https://travis-ci.org/ghorn/generic-accessors.png?branch=master)](https://travis-ci.org/ghorn/generic-accessors)
 
 Get a Tree or list of (String, a -> Double) pairs for use in plotting
 
diff --git a/generic-accessors.cabal b/generic-accessors.cabal
--- a/generic-accessors.cabal
+++ b/generic-accessors.cabal
@@ -1,5 +1,5 @@
 name:                generic-accessors
-version:             0.1.0.1
+version:             0.2.0
 synopsis:            stringly-named getters for generic data
 license:             BSD3
 license-file:        LICENSE
diff --git a/src/Accessors.hs b/src/Accessors.hs
--- a/src/Accessors.hs
+++ b/src/Accessors.hs
@@ -9,6 +9,8 @@
 module Accessors
        ( Lookup(..)
        , AccessorTree(..)
+       , Setter(..)
+       , Getter(..)
        , accessors
        , flatten
        , showTree
@@ -40,19 +42,34 @@
   show = unlines . showAccTree ""
 
 data AccessorTree a = Data (String,String) [(String, AccessorTree a)]
-                    | ATGetter (a -> Double)
+                    | ATGetter (Getter a, Setter a)
 
+data Getter a =
+  GetBool (a -> Bool)
+  | GetDouble (a -> Double)
+  | GetFloat (a -> Float)
+  | GetInt (a -> Int)
+  | GetSorry -- ^ not yet implemented
+
+data Setter a =
+  SetBool (Bool -> a)
+  | SetDouble (Double -> a)
+  | SetFloat (Float -> a)
+  | SetInt (Int -> a)
+  | SetSorry -- ^ not yet implemented
+
 accessors :: Lookup a => a -> AccessorTree a
-accessors = flip toAccessorTree id
+accessors x = toAccessorTree x id id
+--accessors = flip (flip toAccessorTree id) id
 
 showMsgs :: [String] -> String
 showMsgs = intercalate "."
 
-flatten :: AccessorTree a -> [(String, a -> Double)]
+flatten :: AccessorTree a -> [(String, Getter a, Setter a)]
 flatten = flatten' []
 
-flatten' :: [String] -> AccessorTree a -> [(String, a -> Double)]
-flatten' msgs (ATGetter f) = [(showMsgs (reverse msgs), f)]
+flatten' :: [String] -> AccessorTree a -> [(String, Getter a, Setter a)]
+flatten' msgs (ATGetter (get, set)) = [(showMsgs (reverse msgs), get, set)]
 flatten' msgs (Data (_,_) trees) = concatMap f trees
   where
     f (name,tree) = flatten' (name:msgs) tree
@@ -60,224 +77,244 @@
 -- | Things which you can make a tree of labeled getters for.
 -- You should derive this using GHC.Generics.
 class Lookup a where
-  toAccessorTree :: a -> (b -> a) -> AccessorTree b
+  toAccessorTree :: a -> (b -> a) -> (a -> b) -> AccessorTree b
 
-  default toAccessorTree :: (Generic a, GLookup (Rep a)) => a -> (b -> a) -> AccessorTree b
-  toAccessorTree x f = gtoAccessorTree (from x) (from . f)
+  default toAccessorTree :: (Generic a, GLookup (Rep a)) => a -> (b -> a) -> (a -> b) -> AccessorTree b
+  toAccessorTree x get set = gtoAccessorTree (from x) (from . get) (set . to)
 
 class GLookup f where
-  gtoAccessorTree :: f a -> (b -> f a) -> AccessorTree b
+  gtoAccessorTree :: f a -> (b -> f a) -> (f a -> b) -> AccessorTree b
 
 class GLookupS f where
-  gtoAccessorTreeS :: f a -> (b -> f a) -> [(String, AccessorTree b)]
+  gtoAccessorTreeS :: f a -> (b -> f a) -> (f a -> b) -> [(String, AccessorTree b)]
 
 -- some instance from linear
 instance Lookup a => Lookup (Linear.V0 a) where
-  toAccessorTree _ _ =
+  toAccessorTree _ _ _ =
     Data ("V0", "V0") []
 instance Lookup a => Lookup (Linear.V1 a) where
-  toAccessorTree xyz f =
-    Data ("V1", "V1") [ ("x", toAccessorTree (getX xyz) (getX . f))
+  toAccessorTree xyz get set =
+    Data ("V1", "V1") [ ("x", toAccessorTree (getX xyz) (getX . get) (set . setX))
                       ]
     where
       getX (Linear.V1 x) = x
+      setX x = Linear.V1 x
 instance Lookup a => Lookup (Linear.V2 a) where
-  toAccessorTree xyz f =
-    Data ("V2", "V2") [ ("x", toAccessorTree (getX xyz) (getX . f))
-                      , ("y", toAccessorTree (getY xyz) (getY . f))
+  toAccessorTree (Linear.V2 x0 y0) get set =
+    Data ("V2", "V2") [ ("x", toAccessorTree x0 (getX . get) (set . setX))
+                      , ("y", toAccessorTree y0 (getY . get) (set . setY))
                       ]
     where
       getX (Linear.V2 x _) = x
       getY (Linear.V2 _ y) = y
+      setX x = Linear.V2 x  y0
+      setY y = Linear.V2 x0 y
 instance Lookup a => Lookup (Linear.V3 a) where
-  toAccessorTree xyz f =
-    Data ("V3", "V3") [ ("x", toAccessorTree (getX xyz) (getX . f))
-                      , ("y", toAccessorTree (getY xyz) (getY . f))
-                      , ("z", toAccessorTree (getZ xyz) (getZ . f))
+  toAccessorTree (Linear.V3 x0 y0 z0) get set =
+    Data ("V3", "V3") [ ("x", toAccessorTree x0 (getX . get) (set . setX))
+                      , ("y", toAccessorTree y0 (getY . get) (set . setY))
+                      , ("z", toAccessorTree z0 (getZ . get) (set . setZ))
                       ]
     where
       getX (Linear.V3 x _ _) = x
       getY (Linear.V3 _ y _) = y
       getZ (Linear.V3 _ _ z) = z
+      setX x = Linear.V3 x  y0 z0
+      setY y = Linear.V3 x0 y  z0
+      setZ z = Linear.V3 x0 y0 z
 instance Lookup a => Lookup (Linear.V4 a) where
-  toAccessorTree xyz f =
-    Data ("V4", "V4") [ ("x", toAccessorTree (getX xyz) (getX . f))
-                      , ("y", toAccessorTree (getY xyz) (getY . f))
-                      , ("z", toAccessorTree (getZ xyz) (getZ . f))
-                      , ("w", toAccessorTree (getW xyz) (getW . f))
+  toAccessorTree (Linear.V4 x0 y0 z0 w0) get set =
+    Data ("V4", "V4") [ ("x", toAccessorTree x0 (getX . get) (set . setX))
+                      , ("y", toAccessorTree y0 (getY . get) (set . setY))
+                      , ("z", toAccessorTree z0 (getZ . get) (set . setZ))
+                      , ("w", toAccessorTree w0 (getW . get) (set . setW))
                       ]
     where
       getX (Linear.V4 x _ _ _) = x
       getY (Linear.V4 _ y _ _) = y
       getZ (Linear.V4 _ _ z _) = z
       getW (Linear.V4 _ _ _ w) = w
+      setX x = Linear.V4 x  y0 z0 w0
+      setY y = Linear.V4 x0 y  z0 w0
+      setZ z = Linear.V4 x0 y0 z  w0
+      setW w = Linear.V4 x0 y0 z0 w
 instance Lookup a => Lookup (Linear.Quaternion a) where
-  toAccessorTree xyz f =
+  toAccessorTree (Linear.Quaternion q0 (Linear.V3 x0 y0 z0)) get set =
     Data ("Quaternion", "Quaternion")
-    [ ("q0", toAccessorTree (getQ0 xyz) (getQ0 . f))
-    , ("q1", toAccessorTree (getQ1 xyz) (getQ1 . f))
-    , ("q2", toAccessorTree (getQ2 xyz) (getQ2 . f))
-    , ("q3", toAccessorTree (getQ3 xyz) (getQ3 . f))
+    [ ("q0", toAccessorTree q0 (getQ0 . get) (set . setQ0))
+    , ("q1", toAccessorTree x0 (getQ1 . get) (set . setQ1))
+    , ("q2", toAccessorTree y0 (getQ2 . get) (set . setQ2))
+    , ("q3", toAccessorTree z0 (getQ3 . get) (set . setQ3))
     ]
     where
-      getQ0 (Linear.Quaternion q0 _) = q0
+      getQ0 (Linear.Quaternion q _) = q
       getQ1 (Linear.Quaternion _ (Linear.V3 x _ _)) = x
       getQ2 (Linear.Quaternion _ (Linear.V3 _ y _)) = y
       getQ3 (Linear.Quaternion _ (Linear.V3 _ _ z)) = z
 
+      setQ0 q = (Linear.Quaternion q  (Linear.V3 x0 y0 z0))
+      setQ1 x = (Linear.Quaternion q0 (Linear.V3 x  y0 z0))
+      setQ2 y = (Linear.Quaternion q0 (Linear.V3 x0 y  z0))
+      setQ3 z = (Linear.Quaternion q0 (Linear.V3 x0 y0 z ))
 
+
 instance Lookup f => GLookup (Rec0 f) where
-  gtoAccessorTree x f = toAccessorTree (unK1 x) (unK1 . f)
+  gtoAccessorTree x get set = toAccessorTree (unK1 x) (unK1 . get) (set . K1)
 
 instance (Selector s, GLookup a) => GLookupS (S1 s a) where
-  gtoAccessorTreeS x f = [(selname, gtoAccessorTree (unM1 x) (unM1 . f))]
+  gtoAccessorTreeS x get set = [(selname, gtoAccessorTree (unM1 x) (unM1 . get) (set . M1))]
     where
       selname = case selName x of
         [] -> "()"
         y -> y
 
 instance GLookupS U1 where
-  gtoAccessorTreeS _ _ = []
+  gtoAccessorTreeS _ _ _ = []
 
 instance (GLookupS f, GLookupS g) => GLookupS (f :*: g) where
-  gtoAccessorTreeS (x :*: y) f = tf ++ tg
+  gtoAccessorTreeS (x :*: y) get set = tf ++ tg
     where
-      tf = gtoAccessorTreeS x $ left . f
-      tg = gtoAccessorTreeS y $ right . f
+      tf = gtoAccessorTreeS x (getLeft  . get) (set . setLeft)
+      tg = gtoAccessorTreeS y (getRight . get) (set . setRight)
 
-      left  ( x' :*: _  ) = x'
-      right ( _  :*: y' ) = y'
+      getLeft  (x' :*: _ ) = x'
+      getRight (_  :*: y') = y'
 
+      setLeft  x' = x' :*: y
+      setRight y' = x  :*: y'
+
 instance (Datatype d, Constructor c, GLookupS a) => GLookup (D1 d (C1 c a)) where
-  gtoAccessorTree d@(M1 c) f = Data (datatypeName d, conName c) con
+  gtoAccessorTree d@(M1 c) get set = Data (datatypeName d, conName c) con
     where
-      con = gtoAccessorTreeS (unM1 c) (unM1 . unM1 . f)
+      con = gtoAccessorTreeS (unM1 c) (unM1 . unM1 . get) (set . M1 . M1)
 
 -- basic types
 instance Lookup () where -- hack to get dummy tree
-  toAccessorTree _ _ = ATGetter $ const 0
+  toAccessorTree _ _ _ = ATGetter (GetSorry, SetSorry)
 instance Lookup Int where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get set = ATGetter (GetInt get, SetInt set)
 instance Lookup Float where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get set = ATGetter (GetFloat get, SetFloat set)
 instance Lookup Double where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get set = ATGetter (GetDouble get, SetDouble set)
 instance Lookup Bool where
-  toAccessorTree _ f = ATGetter $ realToFrac . fromEnum . f
+  toAccessorTree _ get set = ATGetter (GetBool get, SetBool set)
 
 -- Word types
 instance Lookup Word where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _ = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup Word8 where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _ = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup Word16 where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _ = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup Word32 where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _ = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup Word64 where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _ = ATGetter (GetDouble (realToFrac . get), SetSorry)
 
 -- Int types
 instance Lookup Int8 where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _ = ATGetter (GetInt (fromIntegral . get), SetSorry)
 instance Lookup Int16 where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _ = ATGetter (GetInt (fromIntegral . get), SetSorry)
 instance Lookup Int32 where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _ = ATGetter (GetInt (fromIntegral . get), SetSorry)
 instance Lookup Int64 where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _ = ATGetter (GetInt (fromIntegral . get), SetSorry)
 
+-- todo(greg): some of these getters can fit in ints
 -- C types
 instance Lookup CChar where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CSChar where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CUChar where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CShort where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CUShort where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CInt where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CUInt where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CLong where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CULong where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CPtrdiff where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CSize where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CWchar where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CSigAtomic where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CLLong where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CULLong where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CIntPtr where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CUIntPtr where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CIntMax where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CUIntMax where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CClock where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CTime where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CUSeconds where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CSUSeconds where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get _set = ATGetter (GetDouble (realToFrac . get), SetSorry)
 instance Lookup CFloat where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get set = ATGetter (GetFloat (realToFrac . get), SetFloat (set . realToFrac))
 instance Lookup CDouble where
-  toAccessorTree _ f = ATGetter $ realToFrac . f
+  toAccessorTree _ get set = ATGetter (GetDouble (realToFrac . get), SetDouble (set . realToFrac))
 
 -- other types
 instance Lookup a => Lookup (Rot f1 f2 a) where
-  toAccessorTree x f = toAccessorTree (unR x) (unR . f)
+  toAccessorTree x get set = toAccessorTree (unR x) (unR . get) (set . Rot)
 instance Lookup a => Lookup (V3T f a) where
-  toAccessorTree x f = toAccessorTree (unV x) (unV . f)
+  toAccessorTree x get set = toAccessorTree (unV x) (unV . get) (set . V3T)
 instance Lookup a => Lookup (Euler a)
 
-showAccTrees :: (Double -> String) -> a -> [(String, AccessorTree a)] -> String -> [String]
-showAccTrees show' x trees spaces = concat cs ++ [spaces ++ "}"]
+showAccTrees :: (Getter a -> String) -> [(String, AccessorTree a)] -> String -> [String]
+showAccTrees show' trees spaces = concat cs ++ [spaces ++ "}"]
   where
-    cs = zipWith (showRecordField show' x spaces) trees ("{ " : repeat ", ")
+    cs = zipWith (showRecordField show' spaces) trees ("{ " : repeat ", ")
 
-showRecordField :: (Double -> String) -> a -> String -> (String, AccessorTree a) -> String -> [String]
-showRecordField show' x spaces (getterName, ATGetter f) prefix =
-  [spaces ++ prefix ++ getterName ++ " = " ++ show' (f x)]
-showRecordField show' x spaces (getterName, Data (_,cons) trees) prefix =
-  (spaces ++ prefixNameEq ++ cons) : showAccTrees show' x trees newSpaces
+showRecordField :: (Getter a -> String) -> String -> (String, AccessorTree a) -> String -> [String]
+showRecordField show' spaces (getterName, ATGetter (get, _)) prefix =
+  [spaces ++ prefix ++ getterName ++ " = " ++ show' get]
+showRecordField show' spaces (getterName, Data (_,cons) trees) prefix =
+  (spaces ++ prefixNameEq ++ cons) : showAccTrees show' trees newSpaces
   where
     prefixNameEq = prefix ++ getterName ++ " = "
     newSpaces = spaces ++ (replicate (length prefixNameEq) ' ')
 
 -- | Show a tree of values
-showTree :: AccessorTree a -> (Double -> String) -> a -> String
-showTree (Data (_,cons) trees) show' x = init $ unlines $ cons : showAccTrees show' x trees ""
-showTree (ATGetter f) show' x = show' (f x)
+showTree :: AccessorTree a -> (Getter a -> String) -> String
+showTree (Data (_,cons) trees) show' = init $ unlines $ cons : showAccTrees show' trees ""
+showTree (ATGetter (get,_)) show' = show' get
 
 -- | Show a list of values
 -- .
 -- True --> align the colums, False --> total mayhem
-showFlat :: forall a . AccessorTree a -> Bool -> (Double -> String) -> a -> String
-showFlat at align show' x = init $ unlines $ map f fl
+showFlat :: forall a . AccessorTree a -> Bool -> (Getter a -> String) -> String
+showFlat at align show' = init $ unlines $ map f fl
   where
-    n = maximum (map (length . fst) fl)
+    fst3 (z,_,_) = z
+    n = maximum (map (length . fst3) fl)
 
-    f (name, get) = name ++ spaces ++ " = " ++ show' (get x)
+    f (name, get, _) = name ++ spaces ++ " = " ++ show' get
       where
         spaces
           | align = replicate (n - length name) ' '
           | otherwise = ""
 
-    fl :: [(String, a -> Double)]
+    fl :: [(String, Getter a, Setter a)]
     fl = flatten at
