Concrete instance of abstract class

Hi folks, I just wrote this: import Diagrams.Prelude import Diagrams.Backend.Cairo type Dia = Diagram Cairo R2 class Turtlish t where pic :: t s -> Dia state :: t s -> s move :: s -> t s -> t s (>>>),(+++) :: t s -> t s -> t s x >>> y = x +++ move (state x) y The idea is that s is a turtle state, t s contains such a state along with a growing diagram, and >>> superimposes the diagrams after shuffling the right hand t s around according to the s I extract from the left hand t s. But I have different turtles planned. I want a regular turtle, a Sankey turtle which also has a width, and we could imagine sub-turtles that only had the angle or only the position. But in all cases, I think the above class describes how I want to compose diagrams together. I already tried it with monads but I'm now thinking that I want something like the above * instead* of a monad. So how do I use it to make a regular turtle? Maybe something like: data TurtState = TurtState P2 CircleFrac data TurtWorld s = TurtWorld Dia s I know exactly what s is above but otherwise the kinds don't match below. instance Turtlish TurtWorld where pic (TurtWorld d _) = d state (TurtWorld _ s) = s (TurtWorld d1 _) +++ (TurtWorld d2 s2) = TurtWorld (d1 `atop` d2) s2 move (pp,aa) (TurtWorld d (p,a)) = TurtWorld (d # rotate aa # translate pp) ( (p # rotate aa + pp) , (a+aa) ) Naturally, it barfs over move saying: Couldn't match type `s' with `(R2, t0)' `s' is a rigid type variable bound by the type signature for move :: s -> TurtWorld s -> TurtWorld s at turtle.hs:20:3 In the pattern: (pp, aa) In an equation for `move': move (pp, aa) (TurtWorld d (p, a)) = TurtWorld (d # rotate aa # translate pp) ((p # rotate aa + pp), (a + aa)) In the instance declaration for `Turtlish TurtWorld' because it hasn't a clue what (pp,aa) is and wants s totally generic anyway. But what am I supposed to do instead? Isn't it an everyday thing to use a generic pattern with a specific type? TIA, Adrian.

BTW, I also tried adding:
class Turstateish s where
pos :: s -> R2
ang :: s -> CircleFrac
and guarding the instance declaration with it, but that doesn't work cos
I'd have to mention s in the instance declaration, and then the kinds would
go out of sync again.
Adrian.
On 6 June 2013 00:08, Adrian May
Hi folks,
I just wrote this:
import Diagrams.Prelude import Diagrams.Backend.Cairo
type Dia = Diagram Cairo R2
class Turtlish t where pic :: t s -> Dia state :: t s -> s move :: s -> t s -> t s (>>>),(+++) :: t s -> t s -> t s x >>> y = x +++ move (state x) y
The idea is that s is a turtle state, t s contains such a state along with a growing diagram, and >>> superimposes the diagrams after shuffling the right hand t s around according to the s I extract from the left hand t s.
But I have different turtles planned. I want a regular turtle, a Sankey turtle which also has a width, and we could imagine sub-turtles that only had the angle or only the position. But in all cases, I think the above class describes how I want to compose diagrams together. I already tried it with monads but I'm now thinking that I want something like the above * instead* of a monad.
So how do I use it to make a regular turtle? Maybe something like:
data TurtState = TurtState P2 CircleFrac data TurtWorld s = TurtWorld Dia s
I know exactly what s is above but otherwise the kinds don't match below.
instance Turtlish TurtWorld where pic (TurtWorld d _) = d state (TurtWorld _ s) = s (TurtWorld d1 _) +++ (TurtWorld d2 s2) = TurtWorld (d1 `atop` d2) s2 move (pp,aa) (TurtWorld d (p,a)) = TurtWorld (d # rotate aa # translate pp) ( (p # rotate aa + pp) , (a+aa) )
Naturally, it barfs over move saying:
Couldn't match type `s' with `(R2, t0)' `s' is a rigid type variable bound by the type signature for move :: s -> TurtWorld s -> TurtWorld s at turtle.hs:20:3 In the pattern: (pp, aa) In an equation for `move': move (pp, aa) (TurtWorld d (p, a)) = TurtWorld (d # rotate aa # translate pp) ((p # rotate aa + pp), (a + aa)) In the instance declaration for `Turtlish TurtWorld'
because it hasn't a clue what (pp,aa) is and wants s totally generic anyway.
But what am I supposed to do instead? Isn't it an everyday thing to use a generic pattern with a specific type?
TIA, Adrian.

If you can put any s into TurtWorld, then its instance can't assume
there is a pair there. If you want to make an instance that depends
on s being a pair, add it to the class by adding
MultiParamTypeClasses, FlexibleInstances and going:
instance (Angle a) => Turtlish TurtWorld (R2,a) where
pic (TurtWorld d _) = d
state (TurtWorld _ s) = s
(TurtWorld d1 _) +++ (TurtWorld d2 s2) =
TurtWorld (d1 `atop` d2) s2
move (pp,aa) (TurtWorld d (p,a)) = TurtWorld
(d # rotate aa # translate pp)
( (p # rotate aa + pp) , (a+aa)
There, now TurtWorld is an instance of Turtlish, but only when it has
a pair in its s position.
On Wed, Jun 5, 2013 at 12:17 PM, Adrian May
BTW, I also tried adding:
class Turstateish s where pos :: s -> R2 ang :: s -> CircleFrac
and guarding the instance declaration with it, but that doesn't work cos I'd have to mention s in the instance declaration, and then the kinds would go out of sync again.
Adrian.
On 6 June 2013 00:08, Adrian May
wrote: Hi folks,
I just wrote this:
import Diagrams.Prelude import Diagrams.Backend.Cairo
type Dia = Diagram Cairo R2
class Turtlish t where pic :: t s -> Dia state :: t s -> s move :: s -> t s -> t s (>>>),(+++) :: t s -> t s -> t s x >>> y = x +++ move (state x) y
The idea is that s is a turtle state, t s contains such a state along with a growing diagram, and >>> superimposes the diagrams after shuffling the right hand t s around according to the s I extract from the left hand t s.
But I have different turtles planned. I want a regular turtle, a Sankey turtle which also has a width, and we could imagine sub-turtles that only had the angle or only the position. But in all cases, I think the above class describes how I want to compose diagrams together. I already tried it with monads but I'm now thinking that I want something like the above instead of a monad.
So how do I use it to make a regular turtle? Maybe something like:
data TurtState = TurtState P2 CircleFrac data TurtWorld s = TurtWorld Dia s
I know exactly what s is above but otherwise the kinds don't match below.
instance Turtlish TurtWorld where pic (TurtWorld d _) = d state (TurtWorld _ s) = s (TurtWorld d1 _) +++ (TurtWorld d2 s2) = TurtWorld (d1 `atop` d2) s2 move (pp,aa) (TurtWorld d (p,a)) = TurtWorld (d # rotate aa # translate pp) ( (p # rotate aa + pp) , (a+aa) )
Naturally, it barfs over move saying:
Couldn't match type `s' with `(R2, t0)' `s' is a rigid type variable bound by the type signature for move :: s -> TurtWorld s -> TurtWorld s at turtle.hs:20:3 In the pattern: (pp, aa) In an equation for `move': move (pp, aa) (TurtWorld d (p, a)) = TurtWorld (d # rotate aa # translate pp) ((p # rotate aa + pp), (a + aa)) In the instance declaration for `Turtlish TurtWorld'
because it hasn't a clue what (pp,aa) is and wants s totally generic anyway.
But what am I supposed to do instead? Isn't it an everyday thing to use a generic pattern with a specific type?
TIA, Adrian.
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Hi David,
The thing is, it's not always going to be a pair. The next one I have
planned will have a width as well. What's important about it is that I can
extract it from or use it to 'move' a corresponding variety of TurtWorld.
Adrian.
On 6 June 2013 01:02, David McBride
If you can put any s into TurtWorld, then its instance can't assume there is a pair there. If you want to make an instance that depends on s being a pair, add it to the class by adding MultiParamTypeClasses, FlexibleInstances and going:
instance (Angle a) => Turtlish TurtWorld (R2,a) where pic (TurtWorld d _) = d state (TurtWorld _ s) = s (TurtWorld d1 _) +++ (TurtWorld d2 s2) = TurtWorld (d1 `atop` d2) s2 move (pp,aa) (TurtWorld d (p,a)) = TurtWorld (d # rotate aa # translate pp) ( (p # rotate aa + pp) , (a+aa)
There, now TurtWorld is an instance of Turtlish, but only when it has a pair in its s position.
BTW, I also tried adding:
class Turstateish s where pos :: s -> R2 ang :: s -> CircleFrac
and guarding the instance declaration with it, but that doesn't work cos I'd have to mention s in the instance declaration, and then the kinds would go out of sync again.
Adrian.
On 6 June 2013 00:08, Adrian May
wrote: Hi folks,
I just wrote this:
import Diagrams.Prelude import Diagrams.Backend.Cairo
type Dia = Diagram Cairo R2
class Turtlish t where pic :: t s -> Dia state :: t s -> s move :: s -> t s -> t s (>>>),(+++) :: t s -> t s -> t s x >>> y = x +++ move (state x) y
The idea is that s is a turtle state, t s contains such a state along
with
a growing diagram, and >>> superimposes the diagrams after shuffling the right hand t s around according to the s I extract from the left hand t s.
But I have different turtles planned. I want a regular turtle, a Sankey turtle which also has a width, and we could imagine sub-turtles that only had the angle or only the position. But in all cases, I think the above class describes how I want to compose diagrams together. I already
On Wed, Jun 5, 2013 at 12:17 PM, Adrian May
wrote: tried it with monads but I'm now thinking that I want something like the above instead of a monad.
So how do I use it to make a regular turtle? Maybe something like:
data TurtState = TurtState P2 CircleFrac data TurtWorld s = TurtWorld Dia s
I know exactly what s is above but otherwise the kinds don't match below.
instance Turtlish TurtWorld where pic (TurtWorld d _) = d state (TurtWorld _ s) = s (TurtWorld d1 _) +++ (TurtWorld d2 s2) = TurtWorld (d1 `atop` d2) s2 move (pp,aa) (TurtWorld d (p,a)) = TurtWorld (d # rotate aa # translate pp) ( (p # rotate aa + pp) , (a+aa) )
Naturally, it barfs over move saying:
Couldn't match type `s' with `(R2, t0)' `s' is a rigid type variable bound by the type signature for move :: s -> TurtWorld s -> TurtWorld s at turtle.hs:20:3 In the pattern: (pp, aa) In an equation for `move': move (pp, aa) (TurtWorld d (p, a)) = TurtWorld (d # rotate aa # translate pp) ((p # rotate aa + pp), (a + aa)) In the instance declaration for `Turtlish TurtWorld'
because it hasn't a clue what (pp,aa) is and wants s totally generic anyway.
But what am I supposed to do instead? Isn't it an everyday thing to use a generic pattern with a specific type?
TIA, Adrian.
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

On Thu, Jun 06, 2013 at 12:08:46AM +0800, Adrian May wrote:
Hi folks,
I just wrote this:
import Diagrams.Prelude import Diagrams.Backend.Cairo
type Dia = Diagram Cairo R2
class Turtlish t where pic :: t s -> Dia state :: t s -> s move :: s -> t s -> t s (>>>),(+++) :: t s -> t s -> t s x >>> y = x +++ move (state x) y
This does not really make sense (or at least it is not very useful), because it says that a Turtlish thing *must* be able to use *any* type s as its state. But presumably, for each Turtlish thing you have some *particular* type s in mind. I would do this using an associated type, like so: class Turtlish t where type TState t :: * pic :: t -> Dia state :: t -> TState t move :: TState t -> t -> t (>>>),(+++) :: t -> t -> t x >>> y = x +++ move (state x) y This says that to every type t which is an instance of Turtlish, there is an associated type called (TState t). -Brent
The idea is that s is a turtle state, t s contains such a state along with a growing diagram, and >>> superimposes the diagrams after shuffling the right hand t s around according to the s I extract from the left hand t s.
But I have different turtles planned. I want a regular turtle, a Sankey turtle which also has a width, and we could imagine sub-turtles that only had the angle or only the position. But in all cases, I think the above class describes how I want to compose diagrams together. I already tried it with monads but I'm now thinking that I want something like the above * instead* of a monad.
So how do I use it to make a regular turtle? Maybe something like:
data TurtState = TurtState P2 CircleFrac data TurtWorld s = TurtWorld Dia s
I know exactly what s is above but otherwise the kinds don't match below.
instance Turtlish TurtWorld where pic (TurtWorld d _) = d state (TurtWorld _ s) = s (TurtWorld d1 _) +++ (TurtWorld d2 s2) = TurtWorld (d1 `atop` d2) s2 move (pp,aa) (TurtWorld d (p,a)) = TurtWorld (d # rotate aa # translate pp) ( (p # rotate aa + pp) , (a+aa) )
Naturally, it barfs over move saying:
Couldn't match type `s' with `(R2, t0)' `s' is a rigid type variable bound by the type signature for move :: s -> TurtWorld s -> TurtWorld s at turtle.hs:20:3 In the pattern: (pp, aa) In an equation for `move': move (pp, aa) (TurtWorld d (p, a)) = TurtWorld (d # rotate aa # translate pp) ((p # rotate aa + pp), (a + aa)) In the instance declaration for `Turtlish TurtWorld'
because it hasn't a clue what (pp,aa) is and wants s totally generic anyway.
But what am I supposed to do instead? Isn't it an everyday thing to use a generic pattern with a specific type?
TIA, Adrian.
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Hi Brent,
I would do this using an associated type, like so:
class Turtlish t where type TState t :: * pic :: t -> Dia state :: t -> TState t move :: TState t -> t -> t (>>>),(+++) :: t -> t -> t x >>> y = x +++ move (state x) y
Bingo. Just what I needed. But is this a Haskellish thing to do or am I showing my C++ background by even wanting something like this? Anyway, for the sake of any future googlers, I needed {-# LANGUAGE TypeFamilies #-} and completed the instance with: instance Turtlish TurtWorld where type TState TurtWorld = TurtState ... Thanks, Adrian.

I'm starting to tidy it up:
class Turtlish t where
type Context t :: *
type Content t :: *
construct :: Content t -> Context t -> t
destruct :: t -> (Content t, Context t)
combine :: Content t -> Content t -> Content t
contemp :: Context t -> Context t -> Context t
conform :: Context t -> t -> t
present :: t -> Dia
content :: t -> Content t
content = fst.destruct
context :: t -> Context t
context = snd.destruct
(>>>),(+++) :: t -> t -> t
x +++ y = construct (content x `combine` content y) (context x
`contemp` context y)
x >>> y = x +++ conform (context x) y
but I hit this:
turtle.hs:23:32:
Could not deduce (Content t ~ Content t0)
from the context (Turtlish t)
bound by the class declaration for `Turtlish'
at turtle.hs:(9,1)-(24,47)
NB: `Content' is a type function, and may not be injective
In the return type of a call of `content'
In the first argument of `combine', namely `content x'
In the first argument of `construct', namely
`(content x `combine` content y)'
turtle.hs:23:64:
Could not deduce (Context t ~ Context t1)
from the context (Turtlish t)
bound by the class declaration for `Turtlish'
at turtle.hs:(9,1)-(24,47)
NB: `Context' is a type function, and may not be injective
In the return type of a call of `context'
In the first argument of `contemp', namely `context x'
In the second argument of `construct', namely
`(context x `contemp` context y)'
What does this mean, and how do I fix it?
TIA,
Adrian.
On 6 June 2013 11:28, Adrian May
Hi Brent,
I would do this using an associated type, like so:
class Turtlish t where type TState t :: * pic :: t -> Dia state :: t -> TState t move :: TState t -> t -> t (>>>),(+++) :: t -> t -> t x >>> y = x +++ move (state x) y
Bingo. Just what I needed. But is this a Haskellish thing to do or am I showing my C++ background by even wanting something like this? Anyway, for the sake of any future googlers, I needed {-# LANGUAGE TypeFamilies #-} and completed the instance with:
instance Turtlish TurtWorld where type TState TurtWorld = TurtState ...
Thanks, Adrian.

Yippee! I fixed something myself for a change...
class Turtlish t where
type Context t :: *
type Content t :: *
construct :: Content t -> Context t -> t
destruct :: t -> (Content t, Context t)
* combine :: t -> t -> Content t*
* contemp :: t -> t -> Context t*
conform :: Context t -> t -> t
present :: t -> Dia
content :: t -> Content t
content = fst.destruct
context :: t -> Context t
context = snd.destruct
(>>>),(+++) :: t -> t -> t
* x +++ y = construct (x `combine` y) (x `contemp` y)*
x >>> y = x +++ conform (context x) y
Seems like it doesn't like seeing *only* associated types in a signature.
Adrian.
On 6 June 2013 13:40, Adrian May
I'm starting to tidy it up:
class Turtlish t where type Context t :: * type Content t :: * construct :: Content t -> Context t -> t destruct :: t -> (Content t, Context t) combine :: Content t -> Content t -> Content t contemp :: Context t -> Context t -> Context t conform :: Context t -> t -> t present :: t -> Dia content :: t -> Content t content = fst.destruct context :: t -> Context t context = snd.destruct (>>>),(+++) :: t -> t -> t x +++ y = construct (content x `combine` content y) (context x `contemp` context y) x >>> y = x +++ conform (context x) y
but I hit this:
turtle.hs:23:32: Could not deduce (Content t ~ Content t0) from the context (Turtlish t) bound by the class declaration for `Turtlish' at turtle.hs:(9,1)-(24,47) NB: `Content' is a type function, and may not be injective In the return type of a call of `content' In the first argument of `combine', namely `content x' In the first argument of `construct', namely `(content x `combine` content y)'
turtle.hs:23:64: Could not deduce (Context t ~ Context t1) from the context (Turtlish t) bound by the class declaration for `Turtlish' at turtle.hs:(9,1)-(24,47) NB: `Context' is a type function, and may not be injective In the return type of a call of `context' In the first argument of `contemp', namely `context x' In the second argument of `construct', namely `(context x `contemp` context y)'
What does this mean, and how do I fix it?
TIA, Adrian.
On 6 June 2013 11:28, Adrian May
wrote: Hi Brent,
I would do this using an associated type, like so:
class Turtlish t where type TState t :: * pic :: t -> Dia state :: t -> TState t move :: TState t -> t -> t (>>>),(+++) :: t -> t -> t x >>> y = x +++ move (state x) y
Bingo. Just what I needed. But is this a Haskellish thing to do or am I showing my C++ background by even wanting something like this? Anyway, for the sake of any future googlers, I needed {-# LANGUAGE TypeFamilies #-} and completed the instance with:
instance Turtlish TurtWorld where type TState TurtWorld = TurtState ...
Thanks, Adrian.
participants (3)
-
Adrian May
-
Brent Yorgey
-
David McBride