[Haskell-cafe] How to unify these three types with identical structures into one definition?

William Yager will.yager at gmail.com
Sat Dec 15 12:58:33 UTC 2018


There may be some fun to be had with QuantifiedConstraints. I've thought
about solving similar parser/formatter problems this way, extending parsers
via functor composition. Consider:

> data F f = F (f (F f))

> -- Sadly the below does not work. It seems like maybe it should be able
to work?

> instance (forall a . Show a => Show (f a)) => Show (F f) where show (F f)
= "(F " ++ show f ++ ")"


<interactive>:23:10: error:

    • The constraint ‘Show (f a)’

        is no smaller than the instance head ‘Show (F f)’

      (Use UndecidableInstances to permit this)

    • In the instance declaration for ‘Show (F f)’

> -- We can get something almost as good

> class (forall a . Show a => Show (f a)) => Show1 f

> instance Show1 f => Show (F f) where show (F f) = "(F " ++ show f ++ ")"

> instance Show1 Maybe

> show (F $ Just $ F $ Nothing)

"(F Just (F Nothing))"



On Fri, Dec 14, 2018 at 10:52 PM MarLinn <monkleyon at gmail.com> wrote:

> Hi Ducis,
>
> you can parametrise over type variables of other kinds than just *.
>
> If what you write is really what you want, the most straightforward answer
> is simply
>
> 	data ExprG f
> 	    = Var      VarName
> 	    | Enclosed VarName (f Expr) VarName
> 	    | Prefix   (f Expr) (f Expr)
> 	    | Ternary  (f Expr) VarName (f Expr) VarName (f Expr)
> 	
> 	type Expr  = ExprG Identity -- From Data.Functor.Identity
> 	type ExprL = ExprG []
> 	type ExprD = ExprG DList
>
> There is no mention of the word "functor" because you will have to add
> that constraint to the usage sites.
>
> Downside: notice that the deriving clauses are gone because the instances
> aren't as easy to derive any more. Even the simplest and most harmless way
> I know to get that possibility back involves two language extensions:
> StandaloneDeriving and FlexibleInstances. With those you can write
>
> 	deriving instance Show (ExprG Identity)
> 	deriving instance Show (ExprG [])
> 	deriving instance Show (ExprG DList)
> 	deriving instance Eq   (ExprG Identity)
> 	:
>
> I suspect though that what you actually want, but didn't write, is more
> along the lines of
>
> 	data ExprL = … | EnclosedL VarName [ExprL]       VarName | …   -- using ExprL instead of Expr on the right side
>
> 	data ExprD = … | EnclosedD VarName (DList ExprD) VarName | …   -- using ExprD instead of Expr on the right side
>
> The good news is that if you have the first solution, this step is rather
> simple. Because you can just use replace Expr with ExprG f again:
>
> 	data ExprG f
> 	    = Var      VarName
> 	    | Enclosed VarName (f (ExprG f)) VarName
> 	    | Prefix   (f (ExprG f)) (f (ExprG f))
> 	    | Ternary  (f (ExprG f)) VarName (f (ExprG f)) VarName (f (ExprG f))
>
> The better news is that although this looks repetitive and hard to read,
> it's well on the way to discovering the magic of the Free Monad.
>
> Hope this helps.
>
> Cheers,
> MarLinn
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20181215/7eaaff05/attachment.html>


More information about the Haskell-Cafe mailing list