export from module - haskell

Here is a code taken from http://www.angelfire.com/tx4/cus/shapes/haskell98.html .
It compiles and executes correctly in WinGHCi if I comment the names in the module header. But if the names are kept then it does not compile - it reports an error on the name MakeCircle. My question is: if I want to explicitly mention that I want to export MakeCircle, what code changes are required?
module Circle -- (Circle, MakeCircle, getRadius, setRadius)
where
import Shape
class Shape a => Circle a where
getRadius :: a -> Int
setRadius :: a -> Int -> a
instance Shape CircleInstance where
getX = x
getY = y
setX a newx = a {x = newx}
setY a newy = a {y = newy}
moveTo a newx newy = a {x = newx, y = newy}
rMoveTo a deltax deltay = a {x = ((getX a) + deltax), y = ((getY a) + deltay)}
draw a =
putStrLn ("Drawing a Circle at:(" ++ (show (getX a)) ++ "," ++ (show (getY a)) ++
"), radius " ++ (show (getRadius a)))
instance Circle CircleInstance where
getRadius = radius
setRadius a newradius = a {radius = newradius}
data CircleInstance = MakeCircle {x, y, radius :: Int}
deriving(Eq, Show)

MakeCircle is a data constructor for the type CircleInstance. Data constructors can only be exported in combination with their defining type. You will probably also want to export the Circle class methods getRadius and setRadius; with the current export list those methods will be unavailable outside this module.
Change your export list to
module Circle (Circle (..), CircleInstance (MakeCircle), getRadius, setRadius)
This shows two forms of exporting. The export Circle (..) exports the type class Circle and all of its methods, while CircleInstance (MakeCircle) exports the type constructor CircleInstance and only its data constructor MakeCircle. If you were to add a new data constructor for MakeCircle, perhaps a UnitCircle, that constructor wouldn't be exported from the module unless you either mention it in the export list (i.e. CircleInstance (MakeCircle, UnitCircle) ) or use the (..) form of exports.

The export list is incorrect, it should be:
module Circle(Circle, CircleInstance(MakeCircle), getRadius, setRadius)
Or perhaps
module Circle(Circle, CircleInstance(..), getRadius, setRadius)

Related

Haskell Translation Task

I'm new to programming, and I'm having trouble solving a task.
I have to use the function. In that case I have to implement it on a triangle.
I've tried different things but I'm just getting errors and that's why I'd like to ask for help.
data Triangle = Triangle {
tP1 :: Point,
tP2 :: Point,
tP3 :: Point}
deriving (Show)
First, points and vectors are two separate concepts, and should probably be distinct types, not just two different aliases for a 2-tuple.
data Point = Pt Float Float
data Vector = V Float Float
Second, your type class seems to capture the idea of translating collections of points using the same vector. The return type should then be the same as the first argument type, not hard-coded to Point.
class Polygon p where
translatePol :: p -> VectorD -> p
Now you can start simple, and define a Polygon instance for Point. (Think of a point as a degenerate polygon.)
instance Polygon Point where
translatePol (Pt x y) (Mvector v1 v2) = Pt (x + v1) (y + v2)
This can be used to define the instance for Triangle more simply.
instance Polygon Triangle where
translatePol (MTriangle p1 p2 p3) v = MTriangle (t p1) (t p2) (t p3)
where t p = translatePol p v

Haskell: Functor instance for newtype

To level set, here's a simple functor:
data Box a = Box a deriving (Show)
instance Functor Box where
fmap f (Box x) = Box (f x)
This allows us to operate "inside the box":
> fmap succ (Box 1)
Box 2
How do I achieve this same syntactic convenience with a newtype? Let's say I have the following:
newtype Width = Width { unWidth :: Int } deriving (Show)
newtype Height = Height { unHeight :: Int } deriving (Show)
This is a bit clunky:
> Width $ succ $ unWidth (Width 100)
Width {unWidth = 101}
This would be nice:
> fmap succ (Width 100) -- impossible?
Width {unWidth = 101}
Of course, I can't make Width or Height an instance of a Functor since neither has kind * -> *. Although, syntactically they feel no different than Box, and so it seems like it should be possible to operate on the underlying value without all of the manual wrapping and unwrapping.
Also, it isn't satisfying to create n functions like this because of the repetition with every new newtype:
fmapWidth :: (Int -> Int) -> Width -> Width
fmapHeight :: (Int -> Int) -> Height -> Height
How do I lift a function on Ints to be a function on Widths?
First note that newtype is no hurdle here – you can parameterise these just as well as data, and then you have an ordinary functor. Like
{-# LANGUAGE DeriveFunctor #-}
newtype WidthF a = Width { unWidth :: a } deriving (Show, Functor)
type Width = WidthF Int
I wouldn't consider that a good idea, though. Width shouldn't be a functor; it doesn't make sense to store non-number types in it.
One option as user2407038 suggests is to make it a “monomorphic functor”
import Data.MonoTraversable (MonoFunctor(..))
newtype Width = Width { unWidth :: Int } deriving (Show)
instance MonoFunctor Width where
omap f (Width w) = Width $ f w
That too doesn't seem sensible to me – if you map number operations thus in one generic way, then you might just as well give Width instances for Num etc. and use these directly. But then you hardly have better type-system guarantees than a simple
type Width = Int
which can easily be modified without any help, the flip side being that it can easily be mishandled without any type system safeguards.
Instead, I think what you want is probably this:
import Control.Lens
data Box = Box {
width, height :: Int }
widthInPx, heightInPx :: Lens' Box Int
widthInPx f (Box w h) = (`Box`h) <$> f w
heightInPx f (Box w h) = (Box w) <$> f h
Then you can do
> Box 3 4 & widthInPx %~ (*2)
Box 6 4
> Box 4 2 & heightInPx %~ succ
Box 4 3

Printing new types in Haskell

I'm following a tutorial to create a new type. This is my code:
data Shape = Circle Float Float Float | Rectangle Float Float Float Float
When I load the file with ghci and I type:
Circle 10 20 5
It prints this:
<interactive>:29:1:
No instance for (Show Shape) arising from a use of ‘print’
In a stmt of an interactive GHCi command: print it
How can I solve this?
The show function has type:
show :: Show a => a -> String
Which means it only works on things with a Show instances. You can make your types an instance of the Show class by either manually defining an instance or letting the compiler automatically derive one:
data Shape = Circle Float Float Float | Rectangle Float Float Float Float
deriving (Show)
or
instance Show Shape where
show (Circle a b c) = "Circle " ++ show a ++ " " ++ show b ++ " " ++ show c
show (Rectangle a b c d) = ...
I solved it typing this in the interpreter:
:s -u

Instance of Show Haskell

I am doing my homework and I have a problem doing an instance of Show and I can't solve it, I tried a lot of things. I copy you the error and my code below.
My code:
type Height = Float
type Width = Float
type Radius = Float
data Rectangle = Rectangle Height Width
data Circle = Circle Radius
class Shape a where
area :: a -> Float
perimeter :: a -> Float
instance Shape Rectangle where
area (Rectangle h w) = h * w
perimeter (Rectangle b a) = (2*b) + (2*a)
instance Shape Circle where
area (Circle r) = pi * r**2
perimeter (Circle r) = 2*r*pi
type Volume = Float
volumePrism :: (Shape a) => a -> Height -> Volume
volumePrism base height = (area base) * height
surfacePrism ancho largo alto = (2*ancho*largo) + (2*largo*alto) + (2*ancho*alto)
instance Show a => Show (Shape a) where
show (Rectangle h w) = "Rectángulo de base " ++ w ++ "y altura " ++ h
And what the error says:
The first argument of 'Show' should have kind '*'
What you want to do is not possible. Shape is a typeclass, not a data type, so it has no constructors you can pattern match on. You could do something like
instance (Shape a) => Show a where
show shape = "Area: " ++ show (area shape) ++ " Perimeter: " ++ show (perimeter shape)
But this does not seem to be what you want. Instead, you should just define Show for each type individually:
instance Show Rectangle where
show (Rectangle h w) = "Rectangle with base " ++ show w ++ " and height " ++ show h
instance Show Circle where
show (Circle r) = "Circle with radius " ++ show r
The error about the "kind" can be quite cryptic for beginners (and sometimes experienced haskellers!), but in this case it's fairly straightforward. This does involve a new concept, though. In Haskell, you have values which have a type, such as functions, constants, even monadic actions. You can also talk about the "type of a type", what is known as the kind. There are a couple that you should know about and be comfortable using: * and Constraint. Most types you'll see only involve * and arrows between them. All "fully applied" data types should have kind *, it basically just means that it doesn't take any type parameters, so
> :kind Int
Int :: *
> :kind String
String :: *
> :kind IO ()
IO () :: *
> :kind Maybe Int
Maybe Int :: *
> :kind Either String Int
Either String Int :: *
However, you can have higher-kinded types as well:
> :kind IO -- Note lack of ()
IO :: * -> *
> :kind Maybe
Maybe :: * -> *
> :kind Either
Either :: * -> * -> *
Each * just represents another fully applied type. That last detail is important, it means you can't have Either IO Maybe, because that would be a nonsensical type. These can be higher order as well:
> import Control.Monad.State
> :kind StateT
StateT :: * -> (* -> *) -> * -> *
It's the same syntax as with function types, just without kind variables.
The other one you really need to know about is Constraint. This one is specially for typeclasses:
> :kind Show
Show :: * -> Constraint
> :kind Num
Num :: * -> Constraint
> :kind MonadState
MonadState :: * -> (* -> *) -> Constraint
And when fully applied they return a typeclass, rather than a datatype.
In case you're curious, there are GHC extensions that let you work with more complicated kinds, even allowing you to specify the kinds for a type or typeclass. There are some interesting tricks you can do with it, but these are generally considered more advanced features of the type system.
Shape is a typeclass, and you can’t make a typeclass an instance of another typeclass. (You can make all types that are an instance of a typeclass an instance of a different typeclass as well, but that doesn’t appear to be what you’re trying to do here.)
Rather, you appear to want to implement Show on Rectangle. So say that explicitly:
instance Show Rectangle where
show (Rectangle h w) = "Rectángulo de base " ++ w ++ "y altura " ++ h
Your instance declaration is not meaningful. Translated to English it would read as something like "for every a that is an instance of Show, a being an instance of Shape is an instance of Show" or something incomprehensible like that.
Just make Rectangle and Circle instances of Show and leave Shape out of it, unless you want to require that every instance of Shape must be an instance of Show, which is something that you need to put into the declaration of Shape.

typeclasses, overloading and instance declaration

Having this:
data Rectangle = Rectangle Height Width
data Circle = Circle Radius
class Shape a where
area :: a -> Float
perimeter :: a -> Float
instance Shape Rectangle where
area (Rectangle h w) = h * w
perimeter (Rectangle h w) = 2*h+w*2
instance Shape Circle where
area (Circle r) = pi * r**2
perimeter (Circle r) = 2*pi*r
volumenPrism base height = (area base) * height
surfacePrism shape h = (area shape) * 2 + perimeter shape * h
Why cant I write this? a is a type so why doesn't this work?
instance (Shape a) => Eq a where
x==y = area x == area y
Obviously doing like this:
instance Eq Circle where
x==y = area x == area y
first for Circle and then for Rectangle works..but it seems not the right way.
What is it I don't get in all this?
Ty
The fundamental problem is that the type class instance resolution machinery doesn't backtrack. So if you write instance Shape a => Eq a, then whenever the compiler wants to find an Eq instance, the compiler will try to use this instance and for most types it won't work out because they aren't instances of Shape.
If you still really want to do this, you can add
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
at the top of your source file.
You can also work round some of the problems described above by also adding OverlappingInstances to the set of LANGUAGE pragmas, but you will still have a global instance for Eq that will cause significant confusion elsewhere in your program.
It's much better to just enumerate the instances you really need, even if it seems ugly. You can keep the boilerplate to a minimum with a helper function, e.g.
x `areaEq` y = area x == area y
and then
instance Eq Circle where
(==) = areaEq
etc.

Resources