Whats the syntax for the coproduct (disjoint union) of types in Haskell? - haskell

consider the following
data Point=Point{x::Float,y::Float}
data Shape=Circle{centre::Point,radius::Float}
|Rectangle {uleft::Point,bRight::Point}
Here the type Shape is a coproduct of two types Circle and Rectangle. I may want to reuse the types Circle and Rectangle elsewhere. So it would be useful to do this instead:
data Point=Point{x::Float,y::Float}
data Circle=Circle{centre::Point,radius::Float}
data Rectangle=Rectangle {uleft::Point,bRight::Point}
data Shape =Circle | Rectangle
but I get a compilation error when I do this: Circle is declared twice.
Whats the correct syntax for attempting this, or this not possible?

The coproduct of types in Haskell is commonly denoted by Either:
data Either a b = Left a | Right b
type Shape = Either Circle Rectangle
-- so you have shapes as either Left c for some Circle c
-- or Right r for some Rectangle r
This works quite nicely, although for technical reasons it isn't exactly a coproduct. Another common way would be to define a type like so:
data Shape = CircleShape Circle | RectangleShape Rectangle
so that CircleShape :: Circle -> Shape and RectangleShape :: Rectangle -> Shape are your two injections.
It's wrong to say as you do in your question that the original Shape is a coproduct of types Circle and Rectangle, because the latter two aren't types. If you want to set things up so that Circle p r is both a value of type Circle and a value of type Shape, then that's really contrary to the spirit of Haskell's type system (although something similar might be possible with sufficiently many type system extensions).

This isn't directly possible, but you have a few options. In this case, I would go with a GADT indexed by a DataKind:
{-# LANGUAGE DataKinds, GADTs, KindSignatures #-}
data ShapeType = Circle | Rectangle
data Shape :: ShapeType -> * where
CircleShape :: { centre :: Point, radius :: Float } -> Shape Circle
RectangleShape { uleft :: Point, bRight :: Point } -> Shape Rectangle
Then, whenever you wan to deal with shapes in general, you just use Shape a, and if you want a rectangle or a circle specifically, you use Shape Rectangle or Shape Circle, respectively.

Related

Algebraic Types - Haskell

I am working around with algebraic types in Haskell, doing some exercises from a worksheet. I got the following exercises:
Define an algebraic type Point for representing (the coordinates of) points in twodimensional space.
My code for this exercise:
data Point = Point Float Float
deriving (Show)
Using Point, define a modified version PositionedShape of the Shape data type which
includes the centre point of a shape, in addition to its dimensions.
Shape data previously defined:
data Shape = Circle Float |
Rectangle Float Float
deriving (Show)
My code for this exercise:
data PositionedShape = PositionedShape Shape Point
deriving (Show)
Now my question comes in this one:
Define a function:
haskell move :: PositionedShape -> Float -> Float -> PositionedShape
which moves a shape by the given x and y distances
My implementation for this was the following:
move :: PositionedShape -> Float -> Float -> PositionedShape
move (Shape (Point x y)) newX newY = Shape (Point newX newY)
This is returning me this error:
Week8.hs:103:7: error: Not in scope: data constructor ‘Shape’
Failed, modules loaded: none.
Can someone please explain me why this error and how can I solve it? I am getting a bit confused with algebraic types, I tried a lot of things but it just seems I can't get a solution.
You need to pattern match on data constructors (like Circle and Rectangle), not on type constructors as you're trying to do now (like Shape). For PositionedShape, they happen to have the same name, although you completely forgot the match on this one (and in fact, you don't need to care about the inner Shape at all except to copy it through). Also, move is meant to move the shape by the given distances, not to move it to a new given position;.
You need to use the PositionedShape constructor to break apart a PositionedShape You have used the Shape constructor instead.
Try starting with:
move (PositionedShape shape (Point old_x old_y)) [...]
How about
move (PointedShape s (Point x y)) dx dy = PointedShape s (Point (x+dx) (y+dy))

Iterating over custom data types in Haskell

I have a custom data type that looks like this:
data Circle = Circle
{ radius :: Float
, xPosition :: Float
, yPosition :: Float
}
I want to be able to write a scale function that can take a given circle and change its size like this:
aCircle = Circle 1.5 1 1
scaleFn aCircle 10
The desired output for this example with scale of 10 would be:
Circle 15 10 10
How can I create a function where I can iterate over each field and multiple the values by a constant? In my actual use case I need a way to map over all the fields as there are many of them.
Scaling by a factor is generally a vector space operation. You could do the following:
{-# LANGUAGE TypeFamilies, DeriveGeneric #-}
import Data.VectorSpace
import GHC.Generics (Generic)
data Circle = Circle
{ radius :: Float
, xPosition :: Float
, yPosition :: Float
} deriving (Generic, Show)
instance AdditiveGroup Circle
instance VectorSpace Circle where
type Scalar Circle = Float
main = print $ Circle 1.5 1 1 ^* 10
(result: Circle {radius = 15.0, xPosition = 10.0, yPosition = 10.0}).
(requires vector-space >= 0.11, which has just added support for generic-derived instances.)
However I should remark that Circle as such is not really a good VectorSpace instance: adding two circles doesn't make any sense, and scaling by a negative factor gives a bogus radius. Only define such an instance if your real use case follows the actual vector space axioms.
What you really want for a type like Circle is something like diagrams' Transformable class. But I don't think there's any automatic way to derive an instance for that. In fact, since diagrams has – unfortunately IMO – switched from vector-space to linear, something like this has become considerably tougher to do even in principle.
You can use "scrap your boilerplate":
import Data.Generics
data Circle = Circle
{ radius :: Float
, xPosition :: Float
, yPosition :: Float
}
deriving (Show, Data)
circleModify :: (Float -> Float) -> Circle -> Circle
circleModify f = gmapT (mkT f)
Intuitively, above, mkT f transforms f into a function which is applicable to any type: if the argument of mkT f is a Float, then f is applied, otherwise the argument is returned as it is.
The newly constructed general function is called a "transformation": the T in mkT stands for that.
Then, gmapT applies the transformation mkT f to all the fields of the circle. Note that is a field contained, say, (Float, Bool) that float would be unaffected. Use everywhere instead of gmapT to recursively go deeper.
Note that I'm not a big fan of this approach. If for any reason you change the type of a field, that change will not trigger a type error but gmapT (mkT ...) will now simply skip over that field.
Generic programming can be convenient, but sometimes a bit too much, in that type errors can be silently transformed into unexpected results at runtime. Use with care.

Using subclass implementation in the definition of superclass functions

In my Haskell program I have some typeclasses representing abstract notions of "shapes", namely
-- | Class representing shapes.
class Shape a where
isColliding :: (Shape b) => a -> b -> Bool
centroid :: Point
-- | Class representing shapes composed of a finite number of vertices
and line segments connecting them.
class (Shape a) => Polygon a where
vertices :: a -> Vertices
As you can see, Polygon is naturally a subclass of Shape. I also have some data types that are instances of these different typeclasses. For example:
data Box = Box Point Point Angle
instance Shape Box where
...
instance Polygon Box where
...
---------------------------------
data Circle = Circle Point Radius
instance Shape Circle where
...
I have many more possible shapes, such as NGon, RegularNGon, etc. I would like to be able to implement isColliding, but the information required to calculate whether two shapes are colliding is dependent upon the implementation of the specific instance of Shape. For example, to calculate if two boxes are colliding, I need their list of vertices. So I have a few questions:
Is there anyway to "specialize" my function isColliding so that it is defined in a specific way for collisions of the type isColliding :: (Polygon b) => Box -> b -> Bool?
Is the structuring of my datatypes the best way to approach this problem, or am I misusing typeclasses and datatypes when the whole thing could be restructured to eliminate this problem?
I am rather new to Haskell, so if my question is worded poorly or any clarification is needed, please tell me.
Your current Shape class says “isColliding can tell whether this shape intersects another shape using only the methods of Shape on the other shape”, because its signature (Shape b) => a -> b -> Bool only tells you that b has an instance of Shape. So you’re right that this isn’t quite what you want.
One thing you can do is use MultiParamTypeClasses to describe a relationship between two types:
{-# LANGUAGE MultiParamTypeClasses #-}
class Colliding a b where
collidesWith :: a -> b -> Bool
And then make instances for various concrete combinations of types:
instance Colliding Circle Box where
Circle p r `collidesWith` Box p1 p2 θ = {- … -}
Here you know the concrete types of both a and b when defining the implementation. That might be good enough for your use case.
However, this leaves you with n2 instances if you have n types. And you’ll run into problems if you try to define polymorphic instances like this:
instance (HasBoundingBox b) => Colliding Circle b where
collidesWith = {- … -}
Because this overlaps with all your other instances for Colliding Circle: b will match any type, and only add the constraint that b must have an instance of HasBoundingBox. That constraint is checked after instance resolution. You can work around this with OverlappingInstances or the newer OVERLAPPABLE/OVERLAPPING/OVERLAPS pragmas to tell GHC to choose the most specific matching instance, but this might be more trouble than it’s worth if you’re just getting familiar with Haskell.
I’d have to think on it more, but there are definitely alternative approaches. In the simplest case, if you only need to deal with a few different kinds of shape, then you can just make them a single sum type instead of separate data types:
data Shape
= Circle Point Radius
| Box Point Point Angle
| …
Then your isColliding function can be of type Shape -> Shape -> Bool and just pattern-match on this type.
Generally speaking, if you’re writing a typeclass, it should come with laws for how instances should behave, like mappend x mempty == mappend mempty x == x from Data.Monoid. If you can’t think of any equations that should always hold for instances of your class, you should prefer to represent things with plain old functions and data types instead.

Creating figures in Haskell

Im trying to create datatype "Figure" in Haskell, this datatype should have multiple values:
Square (with parameter length)
Triangle (with parameter length)
Circle (with parameter radius)
Every figure should have a color as well (let's say black and white), this is how my code currently looks like but this doesn't work.
Can anyone help me?
class Figure_ a where
perimeter :: a -> Double
area :: a -> Double
data Figure = forall a. Figure_ a => Figure a
type Radius = Double
type Side = Double
type Color = String
data Circle = Circle Radius
data Triangle = Triangle Side
data Square = Square Side
instance Figure_ Circle where
perimeter (Circle r) = 2 * pi * r
area (Circle r) = pi * r * r
instance Figure_ Triangle where
perimeter (Triangle x y) = 2*(x + y)
area (Triangle x y) = x * y
instance Figure_ Square where
perimeter (Square s) = 4*s
area (Square s) = s*s
instance Figure_ Figure where
perimeter (Figure shape) = perimeter shape
For forall use:
{-# LANGUAGE ExistentialQuantification #-}
Also, your triangle is accepting two parameters, so it should be like this:
data Triangle = Triangle Side Side
But looking at the formula of your Triangle, I think you seem to be confusing it with Rectangle. Also, indentation of your code doesn't seem to be correct. Your code should look like this:
class Figure_ a where
perimeter :: a -> Double
area :: a -> Double
The same indentation rule should also be followed when you create instance of that typeclass.
Im trying to create datatype "Figure" in Haskell, this datatype should have multiple values:
Square (with parameter length)
...
Circle (with parameter radius)
I'm leaving out the triangle to avoid thinking about geometry. Anyway, the questions sounds like you might want the following:
data Figure = Square Double | ... | Circle Double
And then you can define functions like:
area :: Figure -> Double
area (Square side) = side * side
area ... = ...
area (Circle radius) = pi * radius * radius
If you only need one datatype, you don't need classes in Haskell. Haskell classes are for having more than one datatype when they all support a common interface.
There is one reason to prefer your construction with class and forall over the otherwise simpler version with just data: In your version, it is easier to add another kind of figure that was not planned for. If you feel you need this, you might want to read about the existential typeclass antipattern. But if you're just trying to represent figures in Haskell at all, I would certainly start with a simple datatype.

Ambiguous type variable 'blah' in the constraint... how to fix?

I'm trying to write a simple ray-tracer in Haskell. I wanted to define a typeclass representing the various kinds of surfaces available, with a function to determine where a ray intersects them:
{-# LANGUAGE RankNTypes #-}
data Vector = Vector Double Double Double
data Ray = Ray Vector Vector
class Surface s where
intersections :: s -> Ray -> [Vector]
-- Obviously there would be some concrete surface implementations here...
data Renderable = Renderable
{ surface :: (Surface s) => s
, otherStuff :: Int
}
getRenderableIntersections :: Renderable -> Ray -> [Vector]
getRenderableIntersections re ra = intersections (surface re) ra
However this gives me the error:
Ambiguous type variable 's' in the constraint:
'Surface'
arising from a use of 'surface'
(The actual code is more complex but I've tried to distill it to something simpler, while keeping the gist of what I'm trying to achieve).
How do I fix this? Or alternatively, given that I come from a standard OO background, what am I fundamentally doing wrong?
Please don't use existential types for this! You could, but there would be no point.
From a functional standpoint you can drop this typeclass notion of Surface entirely. A Surface is something that maps a Ray to a list of Vectors, no? So:
type Surface = Ray -> [Vector]
data Renderable = Renderable
{ surface :: Surface
, otherStuff :: Int
}
Now if you really want, you can have a ToSurface typeclass essentially as you gave:
class ToSurface a where
toSurface :: a -> Surface
But that's just for convenience and ad-hoc polymorphism. Nothing in your model requires it.
In general, there are a very few use cases for existentials, but at least 90% of the time you can substitute an existential with the functions it represents and obtain something cleaner and easier to reason about.
Also, even though it may be a tad too much for you to take in, and the issues don't exactly match, you might find useful some of Conal's writing on denotational design: http://conal.net/blog/posts/thoughts-on-semantics-for-3d-graphics/
In your getRenderableIntersections function you call surface. There is no way for the interpreter to figure out what instance of the class Surface you want to use. If you have two such instances:
instance Surface SurfaceA where
-- ...
instance Surface SurfaceB where
-- ...
How can the interpreter determine the type of surface?
The way you defined Renderable means there is a function surface :: Surface s => Renderable -> s.
Try creating an instance Surface SurfaceA and asking the following type query (given a simple constructor SurfaceA):
> :t surface (Renderable SurfaceA 0) -- What's the type of the expression?
So, what type is this expression? I bet you're expecting SurfaceA. Wrong. Take the type of surface. It takes a Renderable argument and we're passing it a Renderable argument. What is left after that? Surface s => s. That's the type of that expression. We still don't know what type does s represent.
If you want the type to be SurfaceA you need to change your code so it becomes something like surface :: Surface s => Renderable s -> s. This way what s is can be determined, because it is the same s used in Renderable.
EDIT: As suggested by #mokus, you could also try the ExistentialTypes extension. It allows "hiding" away type parameters on the right side of a type declaration.
data Renderable = forall s. Surface s => Renderable
{ surface :: s
, otherStuff :: Int
}
The HaskellWiki page I linked to above even has an example very similar to what you want to do.
EDIT: (By #stusmith) - For the record, I'm including code below which compiles based on these suggestions here. However I've accepted the answer which I think shows a better way of approaching things.
{-# LANGUAGE ExistentialQuantification #-}
data Vector = Vector Double Double Double
data Ray = Ray Vector Vector
class Surface_ s where
intersections :: s -> Ray -> [Vector]
data Surface = forall s. Surface_ s => Surface s
instance Surface_ Surface where
intersections (Surface s) ra = intersections s ra
data Renderable = Renderable
{ surface :: Surface
}
getRenderableIntersections :: Renderable -> Ray -> [Vector]
getRenderableIntersections re ra = intersections (surface re) ra

Resources