I had wanted to write show several things, and writing show 10 times was not clever.
And so I initially created an infix operator to put between everything to do the showing, which was not much better.
But this http://okmij.org/ftp/Haskell/types.html#polyvar-fn was the clever technique.
{-# OPTIONS -fglasgow-exts #-} -- Techinque from http://okmij.org/ftp/Haskell/types.html#polyvar-fn -- canShowList and ssum will take a variable number of arguments
data CanShow where { CanShow :: Show a => a -> CanShow ; CSLit::String->CanShow} instance Show CanShow where show (CanShow a) = show a show (CSLit s) = s
-- The initial type is accumulator, here a simple list class (Show a) => ShowList a r where canShowList :: [CanShow] -> a -> r
-- After accumulating last argument, you can apply a function, e.g. reverse
instance (Show b) => ShowList b [CanShow] where
canShowList l x = reverse $ (CanShow x):l
-- Get next argument instance (Show a,ShowList b r) => ShowList a (b->r) where
canShowList l x = canShowList ((CanShow x):l)
-- Could eat initial fully typed arguments and make tuple with [] sL :: (ShowList a r) => a -> r sL = canShowList []
pio :: [CanShow]->IO() pio = putStr . unlines . (map show)
eatFirstClass :: (forall a r.(ShowList a r)=>(a->r))->[CanShow] eatFirstClass s = s "and more"
-- Using the same technique to do more work -- This example needs the "r->a" FunDep to work: class (Num a)=>ScaledSum a r | r->a where ssum' :: (a,a) -> a -> r
instance ScaledSum Double Double where ssum' (s,t) x = (s*(t+x))
-- As an added bonus we get "context sensativity" instance ScaledSum Double Int where ssum' (s,t) x = floor (s*(t+x))
instance (ScaledSum a p) => ScaledSum a (a->p) where ssum' (s,t) x = ssum' (s,t+x)
ssum a x = ssum' (a,0) x
-- This fails since ::[Int] applies to (print $ build 1 2 3)
--main = print $ build 1 2 3 ::[Int]
-- Use parenthesis to control ::[Int] syntax
main = do
let empty :: [String]
empty = []
full = [1,2,3]
efc = eatFirstClass (sL empty full)
eol = CSLit "\n"
ssI = (ssum 12) 1 (1/2) (-3.5) :: Int
ssD = (ssum 12) 1 (1/2) (-3.5) :: Double
pio (sL "Hi!" (17,'a') eol (1,CSLit ['a']) empty (CSLit "ping\n") full efc ("ssum",ssI,ssD) "Bye!")
let
other = sL "Terminate with ::[CanShow]" full 1 eol 2 eol 3 ::[CanShow]
putStrLn $ show other
=== GHCI ===
*Main> main "Hi!" (17,'a')
(1,a) [] ping
[1,2,3] [[],[1,2,3],"and more"] ("ssum",-24,-24.0) "Bye!" ["Terminate with ::[CanShow]",[1,2,3],1, ,2, ,3]
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell