Can this be improved?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Can this be improved?

haskell-2
Happy Holidays,

I was wondering if it this small snippet of code could be altered to
require fewer OPTIONS -fallow-... switches.

It creates a show-what-i-mean function called "swim" that takes a
variable number of arguments, and treats strings as-is, calling show on
the other arguments.

> {-# OPTIONS -fglasgow-exts #-}
> {-# OPTIONS -fallow-undecidable-instances #-}
> {-# OPTIONS -fallow-incoherent-instances #-}
> {-# OPTIONS -fallow-overlapping-instances #-}
>
> -- Want to show strings "as-is"
>
> class (Show a) => MyShow a where
>   myShow :: a -> String
>   myShow = show
>
> instance MyShow String where
>   myShow = id
>
> instance (Show b) => MyShow b
>
> -- Want to take variable number of arguments
>
> class PVShow a r  where
>    pvShow :: String -> a -> r
>
> instance (MyShow b) => PVShow b String where
>    pvShow oldString b = oldString ++ (myShow b)
>
> instance (MyShow b,PVShow a r) => PVShow b (a->r) where
>    pvShow oldString b = pvShow (oldString ++ (myShow b))
>
> -- swim is short for Show What I Mean
>
> swim :: (PVShow a r) => a -> r
> swim = pvShow ""
>
> -- Demonstates of polymorphic and first class nature of swim
>
> test foo = foo " and " 7 " are "
>
> -- Tests
>
> main = do putStrLn $ swim "Hello" " " "World #" [17,18,19] "!"
>           putStrLn $ test (swim "I also think " [4,5,6]) "cool" "."

GHCI session:
Main> main
Hello World #[17,18,19]!
I also think [4,5,6] and 7 are cool.
*Main>

Could this be improved by TypeEq machinery?  Is there a Haskell 98 way
to make myShow work this way?

--
Chris Kuklewicz
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Can this be improved?

Tomasz Zielonka
On Tue, Dec 27, 2005 at 04:39:34PM +0000, Chris Kuklewicz wrote:
> Happy Holidays,
>
> I was wondering if it this small snippet of code could be altered to
> require fewer OPTIONS -fallow-... switches.
>
> It creates a show-what-i-mean function called "swim" that takes a
> variable number of arguments, and treats strings as-is, calling show on
> the other arguments.

Perhaps you can use the same trick that allows "show" to treat
String = [Char] differently than all other lists? I mean the
showList method.

Best regards
Tomasz

--
I am searching for a programmer who is good at least in some of
[Haskell, ML, C++, Linux, FreeBSD, math] for work in Warsaw, Poland
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Can this be improved?

haskell-2

Tomasz Zielonka wrote:

> On Tue, Dec 27, 2005 at 04:39:34PM +0000, Chris Kuklewicz wrote:
>
>>Happy Holidays,
>>
>>I was wondering if it this small snippet of code could be altered to
>>require fewer OPTIONS -fallow-... switches.
>>
>>It creates a show-what-i-mean function called "swim" that takes a
>>variable number of arguments, and treats strings as-is, calling show on
>>the other arguments.
>
>
> Perhaps you can use the same trick that allows "show" to treat
> String = [Char] differently than all other lists? I mean the
> showList method.
>
> Best regards
> Tomasz
>

That is where the class has a default function to perform showList, and
the instance Show Char where showList = specialized version.

The MyShow class is similar, but does not work without all the
extensions.  I have class Show a => MyShow a where myShow = show.  Then
I have a specialized version for instance MyShow String where myShow = id.

If I wrap everything in a data contructor I get more flexibility, but I
don't yet see how (even with GADT) to simplify things.

--
Chris
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Can this be improved?

Bruno Oliveira-5
In reply to this post by haskell-2
Hello,

On Tue, 27 Dec 2005 16:39:34 +0000, Chris Kuklewicz wrote:

>Happy Holidays,

>I was wondering if it this small snippet of code could be altered to
>require fewer OPTIONS -fallow-... switches.

Here is a partial solution using only -fglasgow-exts:

> module MyShow where

> class MyShow t where
>     swim :: String -> t

> instance MyShow String where
>     swim = id

> instance (Show a, MyShow t) => MyShow (a -> t) where
>     swim s x = swim (s ++ show x)

> test foo = foo " and " 7 " are "

> main = do putStrLn $ swim "Hello" " " "World #" [17,18,19] "!"
>           putStrLn $ test (swim "I also think " [4,5,6]) "cool" "."

The problem of this solution is that, because we are using show in the
definition of swim for (a -> t), the strings are beeing printed with extra
"\"".

*MyShow> main
Hello" ""World #"[17,18,19]"!"
I also think [4,5,6]" and "7" are ""cool""."

You can, ofcourse, add a new instance for (String -> t) but that will
cost you -fallow-incoherent-instances and -fallow-overlapping-instances.

> instance MyShow t => MyShow (String -> t) where
>     swim s x = swim (s ++ x)

>Could this be improved by TypeEq machinery?  Is there a Haskell 98 way
>to make myShow work this way?

The problem of the previous solution is that you do not want, in the general case,
use the default instance of Show for Strings. An alternative is to just introduce
a newtype S (isomorphic to String) that allows you to handle Strings differently:

> module MyShow where

> class MyShow t where
>     swim :: S -> t

> newtype S = S {unS :: String}

> instance MyShow S where
>     swim = id

> instance Show S where
>     show = unS

> instance (Show a, MyShow t) => MyShow (a -> t) where
>     swim s x = swim (S $ unS s ++ show x)

> putSLn = putStrLn . unS

> test foo = foo (S " and ") 7 (S " are ")

> main = do putSLn $ swim (S "Hello") (S " ") (S "World #") [17,18,19] (S "!")
>                 putSLn $ test (swim (S "I also think ") [4,5,6]) (S "cool") (S ".")

By using the newtype S instead of Haskell String, you obtain an Haskell 98
solution. I am not sure if this is good enough for you but it seems a good compromise.

Hope it helps!

Cheers,

Bruno


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Can this be improved?

haskell-2
Bruno Oliveira wrote:
> On Tue, 27 Dec 2005 16:39:34 +0000, Chris Kuklewicz wrote:
>>I was wondering if it this small snippet of code could be altered to
>>require fewer OPTIONS -fallow-... switches.
>
>
> Here is a partial solution using only -fglasgow-exts:

...deleted...

> The problem of this solution is that, because we are using show in the
> definition of swim for (a -> t), the strings are beeing printed with extra
> "\"".
>
> *MyShow> main
> Hello" ""World #"[17,18,19]"!"
> I also think [4,5,6]" and "7" are ""cool""."

The extra double quotes being what I am trying to avoid with MyShow

>
>>instance MyShow t => MyShow (String -> t) where
>>    swim s x = swim (s ++ x)

This is interesting.  It does remove the need for
-fallow-undecidable-instances.  Thanks.


>>Could this be improved by TypeEq machinery?  Is there a Haskell 98 way
>>to make myShow work this way?
>
>
> The problem of the previous solution is that you do not want, in the general case,
> use the default instance of Show for Strings. An alternative is to just introduce
> a newtype S (isomorphic to String) that allows you to handle Strings differently:
>
... deleted...
>
> By using the newtype S instead of Haskell String, you obtain an Haskell 98
> solution. I am not sure if this is good enough for you but it seems a good compromise.
>
> Hope it helps!
>
> Cheers,
>
> Bruno

I did find the newtype solution, and trying to avoid that is what
motivated such ugly switch flipping usage of GHC.  My intuition was that
this example of creating "something like a sub-type-class of Show" which
treats String differently ought to be possible.  And it is possible, and
I would hazard a guess that your solution with "MyShow (String->t)" is
safe in spite of the extra switches.

The sad thing is that the two -fallow switches infect client code that
uses the MyShow module.  So allowing those tricks for class MyShow must
turn on for classes in code that imports MyShow.  If GHC could -fallow
those flags only for certain typeclasses then it would be confinable.

In principle, could GHC ever be extended to confine -fallow this way?

--
Chris
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Can this be improved?

Udo Stenzel
Chris Kuklewicz wrote:
> > *MyShow> main
> > Hello" ""World #"[17,18,19]"!"
> > I also think [4,5,6]" and "7" are ""cool""."
>
> The extra double quotes being what I am trying to avoid with MyShow

This is your only special case, a single list of a sigle type that is
different from other lists?  To avoid undecidable, incoherent and other
nasty instances, just do what the Prelude does:

class MyShow t where
    swim     :: t -> String
    swimList :: [t] -> String
    swimList [] = "[]"
    swimList xs = '[' : foldr1 (\x -> (swim x ++) . (',' :)) "]" xs

instance MyShow Char where
    swim     = (:[])
    swimList = id


Untested, but you get the idea.  It's pure Haskell 98.  Heck, it's
almost Prelude.Show.  It won't scale to more type constructors easily,
but you didn't ask for that ability, either ;-)


Udo.
--
"As far as Clinton supposedly cheating on his wife, what do people think
he's going to do?  Be president of another country while he's president
of ours?"
        -- Tom R., age 12

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe

signature.asc (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Can this be improved?

haskell-2
Udo Stenzel wrote:

> This is your only special case, a single list of a sigle type that is
> different from other lists?  To avoid undecidable, incoherent and other
> nasty instances, just do what the Prelude does:
>
> class MyShow t where
>     swim     :: t -> String
>     swimList :: [t] -> String
>     swimList [] = "[]"
>     swimList xs = '[' : foldr1 (\x -> (swim x ++) . (',' :)) "]" xs
>
> instance MyShow Char where
>     swim     = (:[])
>     swimList = id
>
>
> Untested, but you get the idea.  It's pure Haskell 98.  Heck, it's
> almost Prelude.Show.  It won't scale to more type constructors easily,
> but you didn't ask for that ability, either ;-)
>
>
> Udo.

You example treats Char specially.  I want (swim 'a') to be ("'a'") not
("a").

I want every type but String to eventually use the builtin "show"
function.  This is not what your example does unless I make it longer.
For example, if I wrote

instance MyShow Int where swim = show
instance MyShow Double where swim = show
... many many instances ...

then it would work.

I need for the compiler to understand that MyShow String has swim = id
and MyShow (any other Show instance but String) has swim = show.

GHC can do this, the working examples with -fallow* prove it.  I was
curious if there is some type level programming knowledge in the Haskell
community which would allow me to express (any other Show instance but
String) in a non-overlapping way.

I can read the HList and OOHaskell work, and see the advanced type level
programming, but I am not yet clever enough to derive a solution for MyShow.

--
Chris
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe