And while I'm posting to the list, I'll send something I wish I had found earlier.

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

Reply via email to