Haskell -- Instance constraints bindings - haskell

I am learning Haskell programming language to understand functional programming paradigm.
I was trying to write following code
class Area shape where
area :: (Num n) => shape n -> n
data Quadrilateral t = Rectangle {length::t, width::t} | Square {side::t} deriving(Show)
data CircularShape t = Circle {radius::t} deriving(Show)
instance Area Quadrilateral where
area (Rectangle l w) = l * w
area (Square s ) = s * s
instance Area CircularShape where
area (Circle r) = pi * r * r
main = do
putStrLn . show . area $ Rectangle 10.0 20.0
putStrLn . show . area $ Square 10
putStrLn . show . area $ Circle 10.0
Here is the link for code
I am getting error below,
Error occurred
ERROR line 13 - Cannot justify constraints in instance member binding
*** Expression : area
*** Type : (Area CircularShape, Num a) => CircularShape a -> a
*** Given context : (Area CircularShape, Num a)
*** Constraints : Floating a
I am not able to understand the exact cause of this error. This code was working fine before adding the CircularShape data and it's corresponding instance of Area typeclass.
How I can solve this if I want to use both Quadrilateral and CircularShape ?

Since we are using different compiler, I show you the output of my error window.
box.hs|14 col 23 error| Could not deduce (Floating n) arising from a use of ‘pi’
|| from the context (Num n)
|| bound by the type signature for
|| area :: Num n => CircularShape n -> n
|| at /Users/evan/box.hs:14:5-8
|| Possible fix:
|| add (Floating n) to the context of
|| the type signature for area :: Num n => CircularShape n -> n
|| In the first argument of ‘(*)’, namely ‘pi’
|| In the first argument of ‘(*)’, namely ‘pi * r’
|| In the expression: pi * r * r
Basically, in your typeclass declaration, n is bound into Num which is too generic if you want to multiply it with pi, which is a floating point type.
Try changing Num into Floating
class Area shape where
area :: (Floating n) => shape n -> n
You might get a warning of something like "Defaulting to Double" which is because there are two floating types in haskell, (i.e Float and Double)

Change the type signature of area to
area:: (Floating n) => shape n -> n
Your code didn't work because multiplication with pi requires the type constraint Floating a
Also use print instead of putStrLn . show

Related

Haskell: Non type-variable argument in the constraint

I created some functions to get some comfort with 2D geometry.
In this example I use Geom2D from CubicBezier package.
Complete code of my program: https://gist.github.com/nskeip/3784d651ac646a67c5f246f048949af4
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}
import Geom2D
left :: (Num a) => Point a -> a -> Point a
left (Point x y) n = Point (x - n) y
right :: (Num a) => Point a -> a -> Point a
right (Point x y) n = Point (x + n) y
up :: (Num a) => Point a -> a -> Point a
up (Point x y) n = Point x (y - n)
down :: (Num a) => Point a -> a -> Point a
down (Point x y) n = Point x (y + n)
They work like this:
> (Point 0 0) `up` 10
Point 0.0 -10.0
Where Point is defined like this:
data Point a = Point {
pointX :: !a,
pointY :: !a
} deriving (Eq, Ord, Functor, Foldable, Traversable)
And everything was fine untill I thought: "Hey, it would be nice to make that functions (actualy, operators) work with thigs like Line - not only Point"
So I declared a class (not taking left and right to keep thigs simple):
class Num n => Moving p n where
up' :: n -> p -> p
down' :: n -> p -> p
up' n = down' (-n)
down' n = up' (-n)
And an instance of Moving for Point a data type:
instance Num a => Moving (Point a) a where
up' n (Point x y) = Point x (y - n)
But when I try to use it, I got an error:
✗ ghci ./uno.hs
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( uno.hs, interpreted )
Ok, modules loaded: Main.
*Main> let p = Point { pointX = 0, pointY = 0 }
*Main> up' 10 p
<interactive>:3:1:
Non type-variable argument in the constraint: Moving (Point a) n
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall n a. (Num a, Moving (Point a) n) => Point a
And the thing that confuses me much: I put the FlexibleContexts pragma to the pragma listing in the head, but ghcu still suggest me to get it included.
How can I fix my class / instance to get parametric polymorphism working? :)
And the thing that confuses me much: I put the FlexibleContexts pragma to the pragma listing in the head, but ghcu still suggest me to get it included.
This only enables the extension in the module itself. To write this code in GHCi, you need to enable the extension in GHCi: :set -XFlexibleContexts.
But this is only part of the problem. It looks like for your class p should determine n: you can only move a Point a up and down by a, right? But as it stands, nothing stops you from defining more Moving (Point a) SomeOtherType instances, and the compiler doesn't assume you won't. So a and n in the inferred type are completely unrelated, where you want them to be the same. This can be fixed by adding the FunctionalDependencies extension and changing the class declaration to say
class Num n => Moving p n | p -> n where
which means exactly that there can't be instances with same p and different n.
I think that's enough to make it work. The code will still be underdetermined because it allows any numeric a, but defaulting rules will pick Integer.

Haskell: meaning of the error in GHCI

I'm not able to figure out what this error msg means. I want to define the function distance for the data type below... I do NOT want to use any GHC extensions.. even if the code is ugly, want to understand the error better, before I move on to using the extensions. Can someone please let me know what this error means and how I can get rid of this.
class Vector v where
distance :: v -> v -> Double
-- doesn't make sense, but WTH...
newtype OneD1 a = OD1 a
deriving (Show)
instance Vector (Maybe m) where
distance _ _ = 5.6
instance Vector (OneD1 m) where
distance (OD1 x1) (OD1 x2) = x2-x1
Prelude> :reload
[1 of 1] Compiling Main ( VectorTypeClass.hs, interpreted )
VectorTypeClass.hs:33:33:
Couldn't match expected type `Double' with actual type `m'
`m' is a rigid type variable bound by
the instance declaration
at C:\Users\byamm\Documents\Programming\Haskell\Lab\Expts\VectorTypeClass\VectorTypeClass.hs:32:10
Relevant bindings include
x2 :: m
(bound at C:\Users\byamm\Documents\Programming\Haskell\Lab\Expts\VectorTypeClass\VectorTypeClass.hs:33:27)
x1 :: m
(bound at C:\Users\byamm\Documents\Programming\Haskell\Lab\Expts\VectorTypeClass\VectorTypeClass.hs:33:18)
distance :: OneD1 m -> OneD1 m -> Double
(bound at C:\Users\byamm\Documents\Programming\Haskell\Lab\Expts\VectorTypeClass\VectorTypeClass.hs:33:4)
In the first argument of `(-)', namely `x2'
In the expression: x2 - x1
Failed, modules loaded: none.
Prelude>
instance Vector (OneD1 m) where
This promises that (OdeD1 m) is a vector, for any m. Including OneD1 String, etc.
distance (OD1 x1) (OD1 x2) = x2-x1
Here we try to apply - on two values of type m, which could be absolutely anything. There are two issues here:
m might not be a numeric type -- GHC is not reporting this error, at the moment.
the result of the difference is again of type m, but distance should produce a Double. This is the error GHC is reporting.
You need to restrict m to some numeric type, so that you can use -, and that type must admit a conversion to Double, otherwise you can't satisfy the distance signature.
One trivial way is:
instance Vector (OneD1 Double) where
distance (OD1 x1) (OD1 x2) = x2-x1
Another could be:
instance Real m => Vector (OneD1 m) where
distance (OD1 x1) (OD1 x2) = realToFrac (x2-x1)

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.

Finding norm of vector using hmatrix in haskell

I just started learning Haskell and am having trouble with
using the hmatrix library. I want to write some simple code
to compute the eigenvalue using the power iteration method.
I start with:
c = fromList [4.0, 4.0, 4.0, 4.0]::Vector Double
n = norm2 c
Which creates a vector c and finds the 2-norm of the vector.
Multiplication with c:
c * 2 (Works)
c * 0.5 (Works)
c * pi (Works)
c * n (Error)
I checked that:
>:t pi
pi :: Floating a => a
>:t n
n :: Double
The problem is with the types but I do not know how to get
around it.
Would I need to define my own (/) function in this case?
Update:
The error I obtain from ghci:
Couldn't match expected type `Vector Double'
with actual type `Double'
In the second argument of `(*)', namely `n'
In the expression: c * n
In an equation for `it': it = c * n
You're doing the right thing by checking the types. If we're a bit more explicit, we can see what is going on.
Prelude Numeric.LinearAlgebra> :t let a = 2; b = c * a in a
let a = 2; b = c * a in a :: Vector Double
The problem is that the type of norm2 c is Double and thus cannot be made into a Vector Double
Let's see the value of that polymorphic 2 from earlier.
Prelude Numeric.LinearAlgebra> let a = 2; b = c * a in a
fromList [2.0]
So instead, n = fromList [norm2 c]
Edit: The very same library exposes functions scalar and scale which you should look into.
(*) assumes that both of its arguments have the same type:
(*) :: (Num a) => a -> a -> a
The reason that your first three multiplications worked was because in all three cases the right argument successfully type-checked as a Vector Double!
To see why, let's ask ghci what the types of those three arguments are:
> :t 2
2 :: Num a => a
> :t 0.5
0.5 :: Fractional a => a
> :t pi
pi :: Floating a => a
All three of those are valid Vector Doubles because hmatrix provides the following three instances:
instance Num (Vector Double) where ...
instance Fractional (Vector Double) where ...
instance Floating (Vector Double) where ...
In other words, Haskell will transform 2, 0.5, and pi into Vector Doubles automatically, thanks to those instances.
This explains why your last example does not type check. n has type Double, which means that there is no chance it can ever type-check also as a Vector Double.

"Instance of Integral Float required" error

The file with following function:
type Point = (Float, Float)
type Circle = (Float, Float, Float)
getCircle :: Point -> Point -> Point -> Circle
getCircle (a, b) (c, d) (e, f) = (x, y, r)
where
x = ((a^2+b^2)*(f-d) + (c^2+d^2)*(b-f) + (e^2+f^2)*(d-b)) `div` (a*(f-d)+c*(b-f)+e*(d-b)) `div` 2
y = ((a^2+b^2)*(e-c) + (c^2+d^2)*(a-e) + (e^2+f^2)*(c-a)) `div` (b*(e-c)+d*(a-e)+f*(c-a)) `div` 2
r = sqrt ((a-x)^2 + (b-y)^2)
Throws an error when I try to load it to Hugs:
ERROR "/Users/ak/Desktop/1.hs":4 - Instance of Integral Float required for definition of getCircle
What's the essence of the problem and how can it be fixed?
Thanks.
You should use / in place of div -- 5 / 2, not 5 div 2. The reason is that haskell treats integral and floating point types differently -- they are instances of different typeclasses.
(/) is declared in typeclass Fractional, whereas div is declared in typeclass Integral. Those type classes have a common ancestor Num, but they do not have any subtyping relationships apart from that.
div is integer division and thus just works on Integral instanves. Simply use /

Resources