Matrix constructor and method in Haskell - haskell

So here is a nested list [[1, 2], [3, 4]]
I want to wrap it in a type called Matrix, and make it an instance of the classes Eq, Num, and Show
I have already created (add, sub, mul) operations for nested lists (matrices). How do I overload (+ - *) operators so that + maps to add, - maps to sub, and * maps to mul? So I can do this
> ma = Matrix [[1, 2], [3, 4]]
> mb = Matrix [[5, 6], [7, 8]]
> ma + mb
> ma - mb
> ma * mb
Thanks
EDIT
this is my attempt so far
> add = zipWith (zipWith (+))
> sub = zipWith (zipWith (-))
> data Matrix a = Matrix [[a]] deriving (Eq, Show)
> instance Num (Matrix a)
> where
> (+) x y = Matrix $ add x y
> (-) x y = Matrix $ sub x y
This is what I get from ghci
Couldn't match expected type `[[c0]]' with actual type `Matrix a'
In the first argument of `sub', namely `x'
In the second argument of `($)', namely `sub x y'
In the expression: Matrix $ sub x y
EDIT #2
The last thing I need to figure out right now is
how to I print
1 2
3 4
Instead of Matrix [[1,2],[3,4]]

Are you having a problem with defining a Num instance for your type? Try this code:
data Matrix a = Matrix [[a]]
deriving (Eq)
plus_mat :: Num a => [[a]] -> [[a]] -> [[a]]
plus_mat = zipWith (zipWith (+))
instance Num a => Num (Matrix a)
where
(Matrix a) + (Matrix b) = Matrix $ plus_mat a b
(-) = undefined
(*) = undefined
negate = undefined
abs = undefined
signum = undefined
fromInteger = undefined
Testing:
*Main> Matrix [[1,2],[3,4]] + Matrix [[5,6],[7,8]]
Matrix [[6,8],[10,12]]
Definitions of the remaining class methods are left as exercise.
And here's a Show instance for Matrix:
import Data.List
instance Show a => Show (Matrix a)
where
show (Matrix a) = intercalate "\n" $ map (intercalate " " . map show) a
Testing:
*Main Data.List> Matrix [[1,2,3], [4,5,6]]
1 2 3
4 5 6

If you inspect the type of your add and sub, you will see the issue.
ghci> :t add
add :: Num a => [[a]] -> [[a]] -> [[a]]
ghci> :t sub
sub :: Num a => [[a]] -> [[a]] -> [[a]]
Mikhail's suggestion was to essentially unwrap the 2D list and rewrap it in the Num instance methods. Another way to do this is to modify your add and sub methods to work on Matrices instead. Here I use a "lifting" approach, where I write combinators to "lift" a function from one type to another.
-- unwraps the 2d list from a matrix
unMatrix :: Matrix a -> [[a]]
unMatrix (Matrix m) = m
-- lifts a 2d list operation to be a Matrix operation
liftMatrixOp :: ([[a]] -> [[a]] -> [[a]]) -> Matrix a -> Matrix a -> Matrix a
liftMatrixOp f x y = Matrix $ f (unMatrix x) (unMatrix y)
-- lifts a regular operation to be a 2d list operation
lift2dOp :: (a -> a -> a) -> [[a]] -> [[a]] -> [[a]]
lift2dOp f = zipWith (zipWith f)
With these combinators, defining add and sub is simply a matter of lifting appropriately.
add, sub :: Num a => Matrix a -> Matrix a -> Matrix a
add = liftMatrixOp add2D
sub = liftMatrixOp sub2D
add2D, sub2D :: Num a => [[a]] -> [[a]] -> [[a]]
add2D = lift2dOp (+)
sub2D = lift2dOp (-)
Now that we have functions that work on Matrices, the Num instance is simple
instance (Num a) => Num (Matrix a) where
(+) = add
(-) = sub
..etc..
Of course we could have combined lift2dOp and liftMatrixOp into one convenience function:
-- lifts a regular operation to be a Matrix operation
liftMatrixOp' :: (a -> a -> a) -> Matrix a -> Matrix a -> Matrix a
liftMatrixOp' = liftMatrixOp . lift2dOp
instance (Num a) => Num (Matrix a) where
(+) = liftMatrixOp' (+)
(-) = liftMatrixOp' (-)
(*) = liftMatrixOp' (*)
..etc..
Now you try: define liftMatrix :: (a -> a) -> Matrix a -> Matrix a, a lifting function for unary functions. Now use that to define negate, abs, and signum. The docs suggest that abs x * signum x should always be equivalent to x. See if this is true for our implementation.
ghci> quickCheck (\xs -> let m = Matrix xs in abs m * signum m == m)
+++ OK, passed 100 tests.
In fact, if you write liftMatrix with the more lenient type signature, it can be used to define a Functor instance for Matrices.
liftMatrix :: (a -> b) -> Matrix a -> Matrix b
instance Functor (Matrix a) where
fmap = liftMatrix
Now think about how you could implement fromInteger. Implementing this allows you to do stuff like this in ghci:
ghci> Matrix [[1,2],[3,4]] + 1
Matrix [[2,3],[4,5]]
That's how it works the way I implemented it, anyways. Remember that any numeric literal n in Haskell code is actually transformed into fromInteger n, which is why this works.
I think that's enough fun for now, but if you need more exercises, try getting comfortable with this Arbitrary instance of Matrices:
instance Arbitrary a => Arbitrary (Matrix a) where
arbitrary = liftM Matrix arbitrary

Related

Rotate function in Haskell

I want to write a function in Haskell that rotates the list given as the second argument by the number of positions indicated by the first argument. Using pattern matching, implement a recursive function
I have written the following function:
rotate :: Int -> [a] -> [a]
rotate 0 [y]= [y]
rotate x [y]= rotate((x-1) [tail [y] ++ head [y]])
but this function always produces a error. Is there any way to solve it?
The function should do the following when it runs:
rotate 1 "abcdef"
"bcdefa"
[y] does not mean "let y be a list". It means "this argument is a list containing one element called y". You have the right structure, but you don't need the brackets around the y.
rotate :: Int -> [a] -> [a]
rotate 0 y = y
rotate x y = rotate (x-1) (tail y ++ [head y])
TL&DR
rotate :: Int -> [a] -> [a]
rotate = drop <> take
In Haskell the most concise but also a curious way to rotate a list could be using the Semigroup type class instance of the function type (a -> b). Lets check the relevant part of the instance.
instance Semigroup b => Semigroup (a -> b) where
f <> g = \x -> f x <> g x
First things first, <> is in fact the inline version of the mappend function from the Monoid type class.
Then we see, the Semigroup b => constraint in the type signature states that the return type b should also be a member of Semigroup type class. Since we use drop :: Int -> [a] -> [a] and take :: Int -> [a] -> [a] we can quickly notice that b is in fact another function with type signature [a] -> [a] so it is a member of Semigroup type class if and only if it's b, which happens to be [a] is also a member of the Semigroup type class and it is.
instance Semigroup [a] where
(<>) = (++)
So everything holds so far but how does it work?
We can deduce from the type signatures as follows;
(drop :: Int -> ([a] -> [a])) <> (take :: Int -> ([a] -> [a])) is
\n -> (drop n :: [a] -> [a]) <> (take n :: [a] -> [a]) which is
\n -> \xs -> (drop n xs :: [a]) <> (take n xs :: [a]) which is
\n -> \xs -> (drop n xs) ++ (take n xs)
This is basically better than the answers using recursive ++ operator to add the head as a singleton list to the end of the tail since it yields an O(n^2) time complexity.
I think you want something like this:
rotate :: Int -> [a] -> [a]
rotate 0 x = x
rotate times (x:xs) = rotate (times - 1) (xs ++ [x])

Is there a way to capture a tuple of higher-order functions in Haskell?

I understand that it's impossible to pattern match functions in Haskell, and I fully understand why. However, I have two closely related questions. First, in cases where you'd like to partially apply functions for use later, is there a way of defining and capturing the return if it's a tuple? Or am I wrong, and this is still trying to pattern match functions under my nose?
For example, suppose I'm trying to get the quotient and remainder of a value with various multiples of ten. Then, how would I write something like this?
q, r :: Integral a => a -> a
(q, r) = (12345 `quotRem`)
I realize here, there are separate functions that exist, so I could do this instead:
q, r :: Integral a => a -> a
q = (12345 `quot`)
r = (12345 `rem`)
However, that's a very specific case, and there are unlimited other examples of functions that return tuples that would be nice to generalize. For example, a function that returns the number of evens and odds in a list.
evens, odds :: Integral a => [a] -> Int
(evens, odds) = (length . (filter even), length . (filter odd))
This leads me to my second question. The above works just fine in GHCi.
Prelude> let (evens, odds) = (length . (filter even), length . (filter odd))
Prelude> :t evens
evens :: Integral a => [a] -> Int
Prelude> evens [1..10]
5
What's even more confusing is it even works by "pattern-matching" in the same way that I was playing with (q, r) in the beginning:
Prelude> let evensOdds = (length . (filter even), length . (filter odd))
Prelude> :t evensOdds
evensOdds :: (Integral a1, Integral a) => ([a1] -> Int, [a] -> Int)
Prelude> let (ev,od) = evensOdds
Prelude> :t ev
ev :: Integral a1 => [a1] -> Int
Prelude> ev [1..10]
5
It also works just fine in an actual file loaded into GHCi, even though (evens, odds) doesn't. Why are these two different, and why does the second one work in GHCi at all if it doesn't work normally? Can what's different here be leveraged in some way?
You never pattern matched on a function. You always pattern matched on the pair-constructor (,). Your (even, odds) example
(evens, odds) = (length . (filter even), length . (filter odd))
just works like
(first, second) = (x, y)
It doesn't matter what type x and y have at that point.
Your (q, r) example doesn't work due to quotRem's type. Let's recall it and compare it with (q, r)'s type:
quotRem :: Integral n => n -> n -> (n , n)
quotRem 12345 :: Integral n => n -> (n , n)
(q, r) :: Integral n => (n -> n, n -> n)
As you can see, the pair (q, r)'type differs from quotRem's one. Still, it's possible to write your function:
pairify :: (a -> (b, c)) -> (a -> b, a -> c)
pairify f = (fst . f, snd . f)
(q,r) = pairify (quotRem 12345)
But as you can see we don't gain too much from pairify. By the way, partition from Data.List provides your (even, odds) functionality:
(even, odds) = pairify (partition even)
Look at the type of (12345 `quotRem`):
Integral a => a -> (a, a)
It’s a single function that returns a tuple. If you want to make this into a tuple of functions, you can compose it with fst and snd:
(q, r) = (fst . f, snd . f)
where f = (12345 `quotRem`)
If you want to do this in a point-free way, one way is to use the &&& combinator from Control.Arrow. Its fully general type is:
Arrow a => a b c -> a b d -> a b (c, d)
Specialised to the -> arrow, that’s:
(b -> c) -> (b -> d) -> b -> (c, d)
So it takes two functions, each taking a value of type b, and returns both their results (of types c and d) in a tuple. So here you can do something like this:
split = (fst .) &&& (snd .)
(q, r) = split (12345 `quotRem`)
Whereas if you look at the type of (length . filter even, length . filter odd), it’s a tuple already,
(Integral a, Integral b) => ([a] -> Int, [b] -> Int)
Which is why of course you can destructure this tuple to bind evens and odds.

Undefined error on defined function

I'm trying to implement a function that multiplies polynomials (represented using lists -- 3x^2 + 5x + 2 = P [2,5,3]):
newtype Poly a = P [a]
plus :: Num a => Poly a -> Poly a -> Poly a
plus (P a) (P b) = P (map (\(y,z) -> z + y) (zipWithPadding 0 a b))
where
zipWithPadding :: (Num a) => a -> [a] -> [a] -> [(a, a)]
zipWithPadding e (aa: as) (bb: bs) = ((aa, bb): zipWithPadding e as bs)
zipWithPadding e [] bs = zip (repeat e) bs
zipWithPadding e as [] = zip as (repeat e)
times :: Num a => Poly a -> Poly a -> Poly a
times (P a) (P b) = sum $ multList 0 [] a b
where
multList :: Num a => Int -> [Poly a] -> [a] -> [a] -> [Poly a]
multList _ s [] _ = s
multList e s (aa:as) bs = multList (e + 1) (s ++ (multElement e aa bs)) as bs
multElement :: Num a => Int -> a -> [a] -> [Poly a]
multElement e aa bs = [P $ replicate e 0 ++ (map (*aa) bs)]
instance Num a => Num (Poly a) where
(+) = plus
(*) = times
negate = undefined
fromInteger = undefined
-- No meaningful definitions exist
abs = undefined
signum = undefined
When I tried to run however, I got an undefined error:
*HW04> times (P [1,2,2]) (P [1,2])
*** Exception: Prelude.undefined
I'm confused.
Clearly you are calling one of the undefined methods in the Num instance for Poly.
You can determine which one is being called by using these definitions:
negate = error "Poly negate undefined"
fromInteger = error "Poly fromInteger undefined"
abs = error "Poly abs undefined"
signum = error "Poly signum undefined"
Running your test expression yields:
Poly *** Exception: Poly fromInteger undefined
The problem is in your use of sum which is essentially defined as:
sum xs = foldl (+) 0 xs
It is therefore calling fromInteger 0. You can fix this with:
fromInteger x = P [ fromInteger x ]
Update
The reason fromInteger for Poly a needs to be defined this way is
because we need to construct a list of Num a values, and fromInteger x
is the way to create a Num a from the Integer value x.
A polynomial is not really a Num, although there is a ring monomorphism Num a => a -> Poly a.
Discard that Num instance and use foldl plus instead of sum.
I'm going to take the position that you should not define an instance of a class simply to hijack the class's functions. The minimal definition of a Num instance expects certain functions to be defined; explicitly assigning undefined to those names does not qualify as a definition. Consider that Haskell provides a specific operator (++) for list concatenation instead of simply overloading (+) with an instance like
instance Num [a] where
a + [] = a
[] + b = b
(a:as) + b = a:(as + b)
(*) = undefined
negate = undefined
-- etc
Instead, define a class that does provide the operations you want. In this case, you want a Ring, which is a type along with two operations, addition and multipication, that obey certain laws. (Put briefly, the operations act as you would expect given the integers as an example, except multiplication is not required to be commutative.)
In Haskell, we would define the class as
class Ring a where
rplus :: a -> a -> a -- addition
rmult :: a -> a -> a -- multiplication
rnegate :: a -> a -- negation
runit :: a -- multiplicative identity
rzero :: a -- additive identity, multiplicative zero
Any value with a valid Num instance forms a ring, although you need to define the instances separately.
instance Ring Integer where
rplus = (+)
rmult = (*)
rnegate = negate
rzero = 0
runit = 1
instance Ring Float
rplus = (+)
rmult = (*)
rnegate = negate
rzero = 0
runit = 1
-- etc
You can define an instance of Ring for polynomials, as long as the coefficients form a ring as well.
newtype Poly a = P [a]
instance Ring a => Ring (Poly a) where
-- Take care to handle polynomials with different degree
-- Note the use of rplus and rzero instead of (+) and 0
-- when dealing with coefficients
rplus (P a) (P b) = case (compare (length a) (length b)) of
LT -> rplus (P (rzero:a)) (P b)
EQ -> P $ zipWith rplus a b
GT -> rplus (P a) (P (rzero:b))
-- I leave a correct implementation of rmult as an exercise
-- for the reader.
rmult = ...
rnegate (P coeffs) = P $ map rnegate coeffs
rzero = P [0]
runit = P [1]

Haskell: Understanding algebraic data types better

I'm trying to construct an algebraic data type that represents polynomials. Given the definition that an Integer constant is a polynomial and that if you add two polynomials or multiply two polynomials, it results in a polynomial.
I'm having a difficult time understanding how algebraic data types work in general and how I would even go about producing this. I currently have
data Poly = Const Int |
Add Poly Poly |
Mult Poly Poly
However I don't know what this even means or how to use it, I'm simply going off of examples I've seen of algebraic data types.
I've seen types like
data Tree = NullT |
Node Int Tree Tree
That makes more sense to me, and how to use it. The polynomial example seems so abstract I don't know where to start.
Edit: When I try to implement simple testing functions like:
evalPoly :: Poly -> Int
evalPoly (Const n) = n
I'm met with the error
*Polynomial> evalPoly Poly 1
<interactive>:25:10: Not in scope: data constructor ‘Poly’
*Polynomial>
Edit again: Thank you for all your suggestions and help, it's helped me produce something that's working for my purposes!
You seem to want to make an ADT for polynomials, but I'd prefer to use a Map. First some imports:
import qualified Data.Map as M
import Data.Function (on)
A polynomial is a Map from powers of x to coefficients.
newtype Poly a n = Poly {coeffMap :: M.Map n a} deriving (Show)
lift f = Poly . f . coeffMap
Let's make some simple polynomials:
zero = Poly M.empty -- none of the powers have non-zero coefficients
x = Poly $ M.singleton 1 1 -- x^1 has coefficient 1
constant 0 = zero
constant a = Poly $ M.singleton 0 a -- x^0 has coefficient a
A standard thing to do with a polynomial is evaluate it with a particular value for x.
The fold here takes the partially-calculated b and adds on the new term, a*x^n:
evalAt :: (Num a, Integral n) => a -> Poly a n -> a
evalAt x = M.foldrWithKey (\n a b -> b + a*x^n) 0 . coeffMap
If we want to use a Map function, we can lift it from Map n a to Poly n a.
I'd like to be able to map on the coefficients, but I don't want to make this an instance of Functor because it's a classic student error to apply operations like squaring, applying trigonometrical or logarithmic functions or taking square roots term by term, when in fact only a tiny few things like scalar multiplication, differentiation and integration work like this. Providing fmap encourages you to do wong things like fmap (+1) instead of (+ (constant 1)).
mapCoeffs :: (a -> b) -> Poly a n -> Poly b n
mapCoeffs f = lift (fmap f)
Maps already collect like terms automatically, but we'll want to omit terms with zero coefficients:
strikeZeros :: (Num a,Eq a) => Poly a n -> Poly a n
strikeZeros = lift $ M.filter (/= 0)
Now we can make the instances:
instance (Eq a,Num a,Ord n,Num n) => Eq (Poly a n) where
f == g = f - g == zero
instance (Eq a,Num a,Num n,Ord n) => Num (Poly a n) where
fromInteger = constant . fromInteger
signum (Poly m) | M.null m = zero
| otherwise = let (n,a) = M.findMax m in
Poly $ M.singleton n (signum a)
abs = mapCoeffs abs
negate = mapCoeffs negate
(+) = (strikeZeros.) . (Poly.) . ((M.unionWith (+)) `on` coeffMap)
(Poly m) * (Poly m') = Poly $
M.fromListWith (+) [(n+n',a*a') | (n,a)<-M.assocs m, (n',a')<-M.assocs m']
In action:
ghci> 3*x^4 + 6 + 2*x^7
Poly {coeffMap = fromList [(0,6),(4,3),(7,2)]}
Here's an alternative solution to the other one I posted.
You seem to want to make an ADT for polynomials, where I'd use a Map, but let's go with a list of terms. First some imports:
import Data.Function (on)
import Data.List (sortBy, groupBy, foldl1')
This way a polynomial is a list of terms, sorted with the highest power first, and a term is aX^n, represented by X a n
newtype Poly a n = Poly {terms :: [Term a n]} deriving (Show)
data Term a n = X {coeff :: a, power :: n} deriving (Eq,Show)
Let's make some simple polynomials:
zero = Poly []
x = Poly [X 1 1]
constant :: (Num a,Eq a,Num n) => a -> Poly a n
constant 0 = zero
constant a = Poly [X a 0]
Once we've defined the Num instance, we'll be able to make X 3 4 by writing 3*x^4.
A standard thing to do with a polynomial is evaluate it with a particular value for x.
subst :: (Num a, Integral n) => a -> Term a n -> a
subst x (X a n) = a * x ^ n
evalAt :: (Num a, Integral n) => a -> Poly a n -> a
evalAt x = sum . map (subst x) . terms
I'd like to be able to map on the coefficients, but I don't want to make this an instance of Functor because it's a classic student error to apply operations like squaring, applying trigonometrical or logarithmic functions or taking square roots term by term, when in fact only a tiny few things like scalar multiplication, differentiation and integration work like this. Providing fmap encourages you to do wong things like fmap (+1) instead of (+ (constant 1)).
mapCoeffs :: (a -> b) -> Poly a n -> Poly b n
mapCoeffs f = Poly . map f' . terms
where f' (X a n) = X (f a) n
We'll need to add and multiply terms, and collect like terms. When we collect like terms, we sort in reverse order of power and omit terms with zero coefficients.
addTerm (X a n) (X b m) | n == m = X (a+b) n
| otherwise = error "addTerm: mismatched powers"
multTerm (X a n) (X b m) = X (a*b) (n+m)
collectLikeTerms :: (Num a, Ord n, Eq a) => Poly a n -> Poly a n
collectLikeTerms = Poly . filter ((/= 0).coeff) -- no zero coeffs
. map (foldl1' addTerm) -- add the like powers
. groupBy ((==) `on` power) -- group the like powers
. sortBy (flip compare `on` power) -- sort in reverse powers
. terms
Now we can make the instances:
instance (Eq a,Num a,Ord n,Num n) => Eq (Poly a n) where
f == g = f - g == zero
instance (Eq a,Num a,Num n,Ord n) => Num (Poly a n) where
fromInteger = constant . fromInteger
signum (Poly []) = zero
signum (Poly (t:_)) = constant . signum . coeff $ t
abs = mapCoeffs abs
negate = mapCoeffs negate
(+) = (collectLikeTerms.) . (Poly.) . ((++) `on` terms)
(Poly ts) * (Poly ts') = collectLikeTerms $ Poly [multTerm t t' | t<-ts, t'<-ts']
In action:
ghci> 5*x^2 + 6*x^7 + 2
Poly {terms = [X {coeff = 6, power = 7},X {coeff = 5, power = 2},X {coeff = 2, power = 0}]}

Haskell error No instance for (Floating Int)

This code is to get the distance between 2 points but i got a problem!
UPDATED by #EduardoLeon
rango2 :: Int -> [Int] -> [[Int]] -> [Int]
rango2 a b list = if (verif [(list!!a!!0),(list!!a!!1),(list!!a!!2)] (b)) then [1]
else [0]
verif :: [Int] -> [Int] -> Bool
verif a b = if ((distance a b) > a!!2) then True
else False
difference :: Num a => [a] -> [a] -> [a]
difference xs ys = zipWith (-) xs ys
dotProduct :: Num a => [a] -> [a] -> a
dotProduct xs ys = sum $ zipWith (*) xs ys
distance :: Floating a => [a] -> [a] -> a
distance xs ys = sqrt $ dotProduct zs zs
where
zs = difference xs ys
EDITED: I cant change Int to Float, because im doing operations with lists and now
throw this error!
Proyecto.hs:71:18:
No instance for (Floating Int) arising from a use of `distance'
Possible fix: add an instance declaration for (Floating Int)
In the first argument of `(>)', namely `(distance a b)'
In the expression: ((distance a b) > a !! 2)
In the expression:
if ((distance a b) > a !! 2) then True else False
To answer your concrete question: Unlike more conventional languages, Haskell does not automatically cast integers to floats. In fact, the very notion of casting does not exist in Haskell. You need to use the function fromIntegral to convert integers to other numeric types. You could try the following in ghci:
> let x = 5 :: Integer
> sqrt x
<interactive>:3:1:
No instance for (Floating Integer) arising from a use of `sqrt'
In the expression: sqrt x
In an equation for `it': it = sqrt x
> let y = fromIntegral x :: Double
> sqrt y
2.23606797749979
I would also like to make some other suggestions regarding your coding style:
Decompose your functions into smaller functions that do exactly one thing and do it well.
The function (!!) traverses a linked list to find the n-th element. This is an O(n) operation, which is more expensive than necessary if you intend to retrieve multiple elements from the same list. Prefer solutions that avoid traversing the same list more than once.
Here is how I would find the distance between two points:
difference :: Num a => [a] -> [a] -> [a]
difference xs ys = zipWith (-) xs ys
dotProduct :: Num a => [a] -> [a] -> a
dotProduct xs ys = sum $ zipWith (*) xs ys
distance :: Floating a => [a] -> [a] -> a
distance xs ys = sqrt $ dotProduct zs zs
where
zs = difference xs ys
I was searching and i saw that i need to change Int to Float?
Just change the type signature to Float and things will start working:
verif :: [Float] -> [Float] -> Bool
You need to change the type signature of your code to indicate that it works with floating data since sqrt function operates on that. A more generic solution would be this:
verif :: (Floating a, Ord a) => [a] -> [a] -> Bool
verif a b = if (sqrt((((b!!0)-(a!!0))*((b!!0)-(a!!0)))+(((b!!1)-(a!!1))*((b!!1)-(a!!1)))) < a!!3)
then True
else if (sqrt((((b!!0)-(a!!0))*((b!!0)-(a!!0)))+(((b!!1)-(a!!1))*((b!!1)-(a!!1)))) == a!!3)
then True
else False
The use of the !! function isn't encouraged in Haskell. I would suggest you to rewrite the function in a more functional way.
I suggest that you revisit your design. What are the meanings of the lists a and b in verif? It looks like you are finding the distance between two points. You can create a type:
data Point = Point Double Double
and a function
distance :: Point -> Point -> Double
to make your code much more readable.
This should also eliminate doing the same calculation twice by using a where clause or let binding.

Resources