How do I capture different scopes using the bound library? - haskell

I'm trying to use Edward's bound library to model the graph of levels in my game - at least levels as they are stored representationally, before being realised as OpenGL objects.
A level consists of a bunch of vertices, whereby we can form a wall between pairs of vertices. Vertices are also used to create simple polygons - sectors (rooms). A sector owns walls, but also has some material properties. There is a lot of sharing going on between vertices, walls, sectors and materials, so to exploit the graph-like nature of this, I turned to the bound library.
The code so far is,
-- Vertices live alone and aren't influenced by anything else. Perhaps these
-- should still be a functor, but act like Const?
data Vertex = Vertex
{ vertexPos :: V2 CFloat }
-- Textures also live alone, and are simply a wrapper around the path to the
-- texture.
data Texture = Texture
{ texturePath :: FilePath }
-- A Material needs to refer to one (or more) textures.
data Material a = Material
{ materialDiffuseTexture :: a
, materialNormalMap :: Maybe a
}
-- A Sector needs to refer to materials *and* vertices. How do I reference two
-- types of variables?
data Sector a = Sector
{ sectorFloorMaterial :: a
, sectorWallMaterial :: a
, sectorCeilingMaterial :: a
, sectorVertices :: Vector a -- How do we guarantee these aren't material ids?
, sectorFloorLevel :: Double
, sectorCeilingLevel :: Double
}
-- A wall points to the sectors on either side of the wall, but also its start
-- and end vertices. The same problem with 'Sector' appears here too.
data Wall a = Wall
{ wallFront :: a -- This should be a sector
, wallBack :: Maybe a -- This should also be a sector
, wallV1 :: a -- But this is a vertex
, wallV2 :: a -- This is also a vertex
}
-- Level ties this all together, with the various expressions making up the
-- vertices, the walls between them, the sectors, and the materials.
data Level = Level
{ levelVertices :: IntMap.IntMap Vertex
, levelSectors :: Vector (Scope Int Sector ())
, levelWalls :: Vector (Scope Int Wall ())
, levelMaterials :: Vector (Scope Int Material ())
, levelTextures :: Vector (Scope Int Texture ())
}
However, I'm not sure if I'm putting the pieces together properly here. For example, I have Sector a, where I am using a to identify both vertices and materials. However, it's important that I use the right identifier in the right place!
I'd love to hear feedback on whether or not I'm going in the right direction by modelling this somewhat constrained AST via bound.

Related

Graphs in Haskell [duplicate]

This question already has answers here:
How do you represent a graph in Haskell?
(7 answers)
Closed 1 year ago.
I'm struggling to understand how simple graphs are represented in Haskell. My understanding is that a graph would basically be a list of vertices and edges (pairs of vertices)
I've been looking at the Data.Graph implementation in order to build a Graph constructor with a type variable "a" for a simple graph, but I don't understand what the constructor should look like and how it will store an Edge and a Vertex.
My initial thinking was to base my constructor on a similar logic as a tree:
type Vertex = Int
type Edge = (Vertex, Vertex)
data Graph a = Void | Vertex a [Graph a]
But I'm not sure how the edges are then represented.
It's tempting to try to represent a graph structurally in Haskell ADTs, but this doesn't really work the way it does with trees because of the presence of loops. It would be possible to represent only a spanning tree, but then the remaining edges need to be represented as addresses into the tree, which is possible but awkward and if you need direct addressing anyway, what's the point of having the tree structure at all?† That's why the standard way is to instead just flatten it completely, an array of vertices and a list (or another array) of edges.
(The vertices can't reasonably be stored in a list because that would have too slow direct access.)
If you want to add extra data, like you would add data to list nodes, you can just add them to the vertex data.
{-# LANGUAGE DeriveFunctor #-}
import Data.Vector as V
newtype Vertex a = Vertex { getVertexData :: a }
deriving (Functor, Eq, Show)
type VertexIndex = Int
type Edge = (VertexIndex, VertexIndex)
data Graph a = Graph
{ graphVertices :: V.Vector (Vertex a)
, graphEdges :: V.Vector Edge
} deriving (Functor, Show)
†IMO there are actually valid reasons to want a tree structure, including to support lazyness. This could be used in some kind of comonadic interface; I dabbled with that once, not sure if somebody has done it properly somewhere.
Just for fun, here is a simple (and inefficient) implementation of nonempty connected graphs based on a spanning tree.
data TreeAddress = Here
| Up TreeAddress
| Down Int TreeAddress
data ConnectedGraph a = Vertex
{ vertexContainedData :: a
, managedNeighbours :: [ConnectedGraph a]
, unmanagedNeighbours :: [TreeAddress]
}
To make it a bit less wasteful, TreeAddress could be condensed down into a single Int if we also keep track of the total number of vertices, or at least Integer if we quotient out the number of managed neighbours at each junction.
It would be a fun exercise to write a Comonad instance for this.
Ah, somebody seems to have done this in Scala.
And they use a library that was itself inspired by the Haskell fgl library! I knew somebody had to have done this already. In fact it's quite old.

Haskell inheritance, data, constructors

So I want to define multiple data classes for my Asteroids game/assignment:
data One = One {oneVelocity :: Velocity, onePosition :: Position, (((other properties unique to One)))}
data Two = Two {twoVelocity :: Velocity, twoPosition :: Position, (((other properties unique to Two)))}
data Three = Three {threeVelocity :: Velocity, threePosition :: Position, (((other properties unique to Three)))}
As you can see I have multiple data classes with some overlapping properties (velocity, position). That also meant that I had to give them different names per data class ("oneVelocity", "twoVelocity", ...).
Is there a way I can let these types of data extend something? I thought of using one datatype with multiple constructors, but some of these current data classes are very different and I don't thing they should reside in one data class with multiple constructors.
You should probably use just a single data type for all of these, but parameterised on the specific details:
data MovingObj s = MovingObj
{ velocity :: Velocity
, position :: Position
, specifics :: s }
Then you can create e.g. asteroid :: MovingObj AsteroidSpecifics, but you can also write functions that work with any such moving object like
advance :: TimeStep -> MovingObj s -> MovingObj s
advance h (MovingObj v p s) = MovingObj v (p .+^ h*^v) s
There is no inheritance in Haskell (at least, not the kind you associate with object-oriented classes). You just want composition of data types.
data Particle = Particle { velocity :: Velocity
, position :: Position
}
-- Exercise for the reader: research the GHC extension that
-- allows all three of these types to use the same name `p`
-- for the particle field.
data One = One { p1 :: Particle
, ... }
data Two = Two { p2 :: Particle
, ... }
data Three = Three { p3 :: Particle
, ... }
Or, you can define a type that encapsulates the other properties, and let those be added to different kinds of Particles.
data Properties = One { ... }
| Two { ... }
| Three { ... }
data Particle = Particle { velocity :: Velocity
, position :: Position
, properties :: Properties
}
(Or see #leftaroundabout's answer, which is a nicer way of handling this approach.)

What are lenses used/useful for?

I can't seem to find any explanation of what lenses are used for in practical examples. This short paragraph from the Hackage page is the closest I've found:
This modules provides a convienient way to access and update the elements of a structure. It is very similar to Data.Accessors, but a bit more generic and has fewer dependencies. I particularly like how cleanly it handles nested structures in state monads.
So, what are they used for? What benefits and disadvantages do they have over other methods? Why are they needed?
They offer a clean abstraction over data updates, and are never really "needed." They just let you reason about a problem in a different way.
In some imperative/"object-oriented" programming languages like C, you have the familiar concept of some collection of values (let's call them "structs") and ways to label each value in the collection (the labels are typically called "fields"). This leads to a definition like this:
typedef struct { /* defining a new struct type */
float x; /* field */
float y; /* field */
} Vec2;
typedef struct {
Vec2 col1; /* nested structs */
Vec2 col2;
} Mat2;
You can then create values of this newly defined type like so:
Vec2 vec = { 2.0f, 3.0f };
/* Reading the components of vec */
float foo = vec.x;
/* Writing to the components of vec */
vec.y = foo;
Mat2 mat = { vec, vec };
/* Changing a nested field in the matrix */
mat.col2.x = 4.0f;
Similarly in Haskell, we have data types:
data Vec2 =
Vec2
{ vecX :: Float
, vecY :: Float
}
data Mat2 =
Mat2
{ matCol1 :: Vec2
, matCol2 :: Vec2
}
This data type is then used like this:
let vec = Vec2 2 3
-- Reading the components of vec
foo = vecX vec
-- Creating a new vector with some component changed.
vec2 = vec { vecY = foo }
mat = Mat2 vec2 vec2
However, in Haskell, there's no easy way of changing nested fields in a data structure. This is because you need to re-create all of the wrapping objects around the value that you are changing, because Haskell values are immutable. If you have a matrix like the above in Haskell, and want to change the upper right cell in the matrix, you have to write this:
mat2 = mat { matCol2 = (matCol2 mat) { vecX = 4 } }
It works, but it looks clumsy. So, what someone came up with, is basically this: If you group two things together: the "getter" of a value (like vecX and matCol2 above) with a corresponding function that, given the data structure that the getter belongs to, can create a new data structure with that value changed, you are able to do a lot of neat stuff. For example:
data Data = Data { member :: Int }
-- The "getter" of the member variable
getMember :: Data -> Int
getMember d = member d
-- The "setter" or more accurately "updater" of the member variable
setMember :: Data -> Int -> Data
setMember d m = d { member = m }
memberLens :: (Data -> Int, Data -> Int -> Data)
memberLens = (getMember, setMember)
There are many ways of implementing lenses; for this text, let's say that a lens is like the above:
type Lens a b = (a -> b, a -> b -> a)
I.e. it is the combination of a getter and a setter for some type a which has a field of type b, so memberLens above would be a Lens Data Int. What does this let us do?
Well, let's first make two simple functions that extract the getters and setters from a lens:
getL :: Lens a b -> a -> b
getL (getter, setter) = getter
setL :: Lens a b -> a -> b -> a
setL (getter, setter) = setter
Now, we can start abstracting over stuff. Let's take the situation above again, that we want to modify a value "two stories deep." We add a data structure with another lens:
data Foo = Foo { subData :: Data }
subDataLens :: Lens Foo Data
subDataLens = (subData, \ f s -> f { subData = s }) -- short lens definition
Now, let's add a function that composes two lenses:
(#) :: Lens a b -> Lens b c -> Lens a c
(#) (getter1, setter1) (getter2, setter2) =
(getter2 . getter1, combinedSetter)
where
combinedSetter a x =
let oldInner = getter1 a
newInner = setter2 oldInner x
in setter1 a newInner
The code is kind of quickly written, but I think it's clear what it does: the getters are simply composed; you get the inner data value, and then you read its field. The setter, when it is supposed to alter some value a with the new inner field value of x, first retrieves the old inner data structure, sets its inner field, and then updates the outer data structure with the new inner data structure.
Now, let's make a function that simply increments the value of a lens:
increment :: Lens a Int -> a -> a
increment l a = setL l a (getL l a + 1)
If we have this code, it becomes clear what it does:
d = Data 3
print $ increment memberLens d -- Prints "Data 4", the inner field is updated.
Now, because we can compose lenses, we can also do this:
f = Foo (Data 5)
print $ increment (subDataLens#memberLens) f
-- Prints "Foo (Data 6)", the innermost field is updated.
What all of the lens packages do is essentially to wrap this concept of lenses - the grouping of a "setter" and a "getter," into a neat package that makes them easy to use. In a particular lens implementation, one would be able to write:
with (Foo (Data 5)) $ do
subDataLens . memberLens $= 7
So, you get very close to the C version of the code; it becomes very easy to modify nested values in a tree of data structures.
Lenses are nothing more than this: an easy way of modifying parts of some data. Because it becomes so much easier to reason about certain concepts because of them, they see a wide use in situations where you have huge sets of data structures that have to interact with one another in various ways.
For the pros and cons of lenses, see a recent question here on SO.
Lenses provide convenient ways to edit data structures, in a uniform, compositional way.
Many programs are built around the following operations:
viewing a component of a (possibly nested) data structure
updating fields of (possibly nested) data structures
Lenses provide language support for viewing and editing structures in a way that ensures your edits are consistent; that edits can be composed easily; and that the same code can be used for viewing parts of a structure, as for updating the parts of the structure.
Lenses thus make it easy to write programs from views onto structures; and from structures back on to views (and editors) for those structures. They clean up a lot of the mess of record accessors and setters.
Pierce et al. popularized lenses, e.g. in their Quotient Lenses paper, and implementations for Haskell are now widely used (e.g. fclabels and data-accessors).
For concrete use cases, consider:
graphical user interfaces, where a user is editing information in a structured way
parsers and pretty printers
compilers
synchronizing updating data structures
databases and schemas
and many other situations where you have a data structure model of the world, and a editable view onto that data.
As an additional note it is often overlooked that lenses implement a very generic notion of "field access and update". Lenses can be written for all kinds of things, including function-like objects. It requires a bit of abstract thinking to appreciate this, so let me show you an example of the power of lenses:
at :: (Eq a) => a -> Lens (a -> b) b
Using at you can actually access and manipulate functions with multiple arguments depending on earlier arguments. Just keep in mind that Lens is a category. This is a very useful idiom for locally adjusting functions or other things.
You can also access data by properties or alternate representations:
polar :: (Floating a, RealFloat a) => Lens (Complex a) (a, a)
mag :: (RealFloat a) => Lens (Complex a) a
You can go further writing lenses to access individual bands of a Fourier-transformed signal and a lot more.

How would you represent a graph (the kind associated with the travelling salesman problem) in Haskell

It's pretty easy to represent a tree in haskell:
data Tree a = Node Tree a Tree | Leaf a
but that's because it has no need for the concept of an imperative style "pointer" because each Node/Leaf has one, and only one parent. I guess I could represent it as a list of lists of Maybe Ints ...to create a table with Nothing for those nodes without a path between and Just n for those that do... but that seems really ugly and unwieldy.
You can use a type like
type Graph a = [Node a]
data Node a = Node a [Node a]
The list of nodes is the outgoing (or incoming if you prefer) edges of that node. Since you can build cyclic data structures this can represent arbitrary (multi-)graphs. The drawback of this kind of graph structure is that it cannot be modified once you have built it it. To do traversals each node probably needs a unique name (can be included in the a) so you can keep track of which nodes you have visited.
Disclaimer: below is a mostly pointless exercise in "tying the knot" technique. Fgl is the way to go if you want to actually use your graphs. However if you are wondering how it's possible to represent cyclic data structures functionally, read on.
It is pretty easy to represent a graph in Haskell!
-- a directed graph
data Vertex a b = Vertex { vdata :: a, edges :: [Edge a b] }
data Edge a b = Edge { edata :: b, src :: Vertex a b, dst :: Vertex a b }
-- My graph, with vertices labeled with strings, and edges unlabeled
type Myvertex = Vertex String ()
type Myedge = Edge String ()
-- A couple of helpers for brevity
e :: Myvertex -> Myvertex -> Myedge
e = Edge ()
v :: String -> [Myedge] -> Myvertex
v = Vertex
-- This is a full 5-graph
mygraph5 = map vv [ "one", "two", "three", "four", "five" ] where
vv s = let vk = v s (zipWith e (repeat vk) mygraph5) in vk
This is a cyclic, finite, recursive, purely functional data structure. Not a very efficient or beautiful one, but look, ma, no pointers! Here's an exercise: include incoming edges in the vertex
data Vertex a b = Vertex {vdata::a, outedges::[Edge a b], inedges::[Edge a b]}
It's easy to build a full graph that has two (indistinguishable) copies of each edge:
mygraph5 = map vv [ "one", "two", "three", "four", "five" ] where
vv s =
let vks = repeat vk
vk = v s (zipWith e vks mygraph5)
(zipWith e mygraph5 vks)
in vk
but try to build one that has one copy of each! (Imagine that there's some expensive computation involved in e v1 v2).
The knot-tying techniques that others have outlined can work, but are a bit of a pain, especially when you're trying to construct the graph on the fly. I think the approach you describe is a bit more practical. I would use an array/vector of node types where each node type holds a list/array/vector of neighbors (in addition to any other data you need) represented as ints of the appropriate size, where the int is an index into the node array. I probably wouldn't use Maybe Ints. With Int you can still use -1 or any suitable value as your uninitialized default. Once you have populated all your neighbor lists and know they are good values you won't need the failure machinery provided by Maybe anyway, which as you observed imposes overhead and inconvenience. But your pattern of using Maybe would be the correct thing to do if you needed to make complete use of all possible values the node pointer type could contain.
The simplest way is to give the vertices in the graph unique names (which could be as simple as Ints) and use either the usual adjacency matrix or neighbor list approaches, i.e., if the names are Ints, either use array (Int,Int) Bool, or array Int [Int].
Have a look at this knot-tying technique, it is used to create circular structures. You may need it if your graph contains cycles.
Also, you can represent your graph using the adjacency matrix.
Or you can keep maps between each node and the inbound and outbound edges.
In fact, each of them is useful in one context and a pain in others. Depending on your problem, you'll have to choose.

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