Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PureScript and typeclasses

Tags:

purescript

I'm having trouble with PureScript typeclasses. I have to say, up front, that I'm not a Haskell expert either so my apologies if these are obvious errors.

I've tried several different approaches and hit a wall for each. I'm basically trying to define a show function for an edge in a graph. One approach looks like this:

module Foo where

data Edge n = Edge { from :: n, to :: n }

instance showEdge :: (Show n) => Show (Edge n) where
  show e = "Edge from "++(show e.from)++" to "++(show e.to)

e = Edge { from: 1, to: 2 }

main = show e

This gives me the error:

$ psc src/Attempt1.purs
Error at src/Attempt1.purs line 6, column 27:
Error in declaration showEdge
Cannot unify Prim.Object with Foo.Edge.

I'm guessing this has something to do with the fact that it is inferring the type of e in the definition of show. I tried adding a type annotation here, but I get a syntax error:

module Foo where

data Edge n = Edge { from :: n, to :: n }

instance showEdge :: (Show n) => Show (Edge n) where
  show e :: Edge n
  show e = "Edge from "++(show e.from)++" to "++(show e.to)

e = Edge { from: 1, to: 2 }

main = show e

The second thing I tried was this:

module Foo where

type Edge n = { from :: n, to :: n }

instance showEdge :: (Show n) => Show (Edge n) where
  show e = "Edge from "++(show e.from)++" to "++(show e.to)

e :: Edge Number
e = { from: 1, to: 2 }

main = show e

This gives me:

$ psc src/Attempt2.purs
Error at src/Attempt2.purs line 5, column 1:
Type synonym instances are disallowed

So I then tried explicitly listing the underlying type:

module Foo where

type Edge n = { from :: n, to :: n }

instance showEdge :: (Show n) => Show { from :: n, to :: n } where
  show e = "Edge from "++(show e.from)++" to "++(show e.to)

e :: Edge Number
e = { from: 1, to: 2 }

main = show e

which gives me:

$ psc src/Attempt3.purs
Error at src/Attempt3.purs line 5, column 1:
Error in type (to :: n, from :: n):
Type class instance head is invalid.

I have no idea what the "type class instance head" is, so I've got nowhere to go from there.

All three attempts failed. Probably for completely different reasons. Being new to PureScript, I just don't know what the issue is. I've been trying to following along looking at examples from the various Data.* types and reading PureScript by Example. I haven't been able to figure this out.

Thanks for any assistance.

like image 736
Michael Tiller Avatar asked Oct 16 '14 11:10

Michael Tiller


1 Answers

Actually, you were almost there with your first attempt, the problem you have here is Edge is a data constructor with one field containing an object, whereas the same syntax in Haskell is defining functions for accessing several fields in your data.

Haskell doesn't have objects/records as first class objects the way PureScript does, so all you need to do is unwrap the object from your Edge:

show (Edge e) = "Edge from " ++ show e.from ++ " to " ++ show e.to

like image 133
gb. Avatar answered Oct 19 '22 03:10

gb.