[Haskell-cafe] could not deduce Show compile error

Henning Thielemann lemming at henning-thielemann.de
Fri Jun 2 14:21:02 UTC 2023


On Fri, 2 Jun 2023, Zoran BoĆĄnjak wrote:

> import Prelude hiding ((.), id)
> import Control.Category
>
> data Flow a b where
>    Id      :: Flow a a
>    Compose :: Flow a b -> Flow b c -> Flow a c

type variable 'b' of Compose is not visible outside Flow. Thus you cannot 
get later in runFlow, but you have to embed the Show constraint in the 
Compose constructor like so:

Compose :: (Show b) => Flow a b -> Flow b c -> Flow a c

But this in turn means, you can compose only Flows where the interim type 
'b' is an instance of Show.


To avoid this you would need an additional type parameter to Flow with a 
constraint kind constructor or an existentially quantified type, that 
holds all the constraints you need for your current application.

I think it should be like so:

type family FlowConstraints constr a

data FlowAny
type instance FlowConstraints FlowAny a = ()

data FlowShow
type instance FlowConstraints FlowShow a = (Show a)

data Flow constr a b where
    Id      :: Flow a a
    Compose :: (FlowConstraints constr b) => Flow a b -> Flow b c -> Flow a c


or alternatively:

data family FlowConstraints constr a

data FlowAny
data instance FlowConstraints FlowAby a = FlowAnyConstraint

data FlowShow
data instance FlowConstraints FlowShow a = (Show a) => FlowShowConstraint

data Flow constr a b where
    Id      :: Flow a a
    Compose :: (FlowConstraints constr b) => Flow a b -> Flow b c -> Flow a c

In this case you have to match on FlowAnyConstraint or FlowShowConstraint 
in runFlow in order to get back the required constraints.



In any case, the constraints must already be available at construction 
with Compose. Thus you will not be able to use Compose in a Category 
instance.


More information about the Haskell-Cafe mailing list