Using `newtype` to wrap other types - haskell

I'm trying to understand newtype and thought this would work:
module NT where
newtype X = X Double
newtype Y = Y Double
doit :: X -> Y -> Double
doit x y = x + y
x = X 1.1
y = Y 2.2
-- doit x y should work
-- doit y x should error
The first error produced is:
NT.hs:7:12: error:
• Couldn't match expected type ‘Double’ with actual type ‘X’
• In the expression: X x + Y y
In an equation for ‘doit’: doit x y = X x + Y y
|
7 | doit x y = X x + Y y
|
I get that the types don't match, I just don't understand how to get around it. I thought wrapping Double like this could be used to prevent the mixup of x and y in doit.
Is this true, or am I misunderstanding?

You need to “unwrap” the newtype before + can work.
doit :: X -> Y -> Double
doit (X x) (Y y) = x + y
Here, I am using pattern matching to unwrap the Double inside each argument. Here, x and y are both Double, so you can just add them with x + y.

You unwrap the elements out of the data constructor with pattern matching:
doit :: X -> Y -> Double
doit (X x) (Y y) = x + y
Here the x and y are thus Doubles, since the parameters the X and Y data constructor wrap are Doubles as well.

Related

Type of a value when defined in ghci vs when in script

I am a beginner in haskell and while reading about types, I observed the following and not able to understand the reason for it.
If I define the following values in the script
x = 2
y = x + 3
And now i check for their type, I get the following
*Chapter4> :t x
x :: Integer
*Chapter4> :t y
y :: Integer
If I change the definition of y from y = x + 3 to y = x + 3.1 and again check for type, I get this
*Chapter4> :t y
y :: Double
*Chapter4> :t x
x :: Double
But if instead I define the variables x and y using let in GHCi, in the following way,
*Chapter4> let x = 2
*Chapter4> let y = x + 3
Now i check for types and get this:
*Chapter4> :t x
x :: Num p => p
*Chapter4> :t y
y :: Num a => a
And now I change the definition of y again to y = x + 3.1 and check for type I get this now :
*Chapter4> :t x
x :: Num p => p
*Chapter4> :t y
y :: Fractional a => a
So why this difference in behavior ? Is it something to do with 'let' ?

How to properly implement a helper function in Haskell

The 'gridList' function description:
Takes two Integer inputs,
x and y, and returns a list of tuples representing the coordinates
of each cell from (1,1) to (x,y).
Example Output
$> gridList 3 3
$> [(1,1),(2,1),(3,1),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]
Source Code
gridList :: Integer -> Integer -> [(Integer,Integer)]
gridList 1 1 = [(1,1)]
gridList 1 y = helper 1 y
gridList x y = (helper x y) ++ gridList (x-1) y
where
helper :: Integer -> Integer -> [(Integer, Integer)]
helper x 1 = [(x,1)]
helper x y = (x,y) : (helper x (y-1))
Question: The code doesn't compile giving the following error: Variable not in scope
referring to the line 3 where the helper is first introduced. Why doesn't the wheresolve this problem?
Thanks
In Haskell, where-bound definitions are in scope only in the equation immediately above the where block. This means that if you define a function using multiple equations, each of them gets a separate where block.
In your case, the definition of helper is in scope only for the third equation (line 4), but not for the first two.
In order to use the same helper definition for all branches, change the definition from three separate equations to a case expression:
gridList :: Integer -> Integer -> [(Integer,Integer)]
gridList x y = case (x, y) of
(1, 1) -> [(1,1)]
(1, _) -> helper 1 y
_ -> (helper x y) ++ gridList (x-1) y
where
helper :: Integer -> Integer -> [(Integer, Integer)]
helper x 1 = [(x,1)]
helper x y = (x,y) : (helper x (y-1))
The problem is that the scope of the where-clause covers only the last equation. I'd usually suggest using a case-expression instead of multiple equations. However, since you are doing pattern matches on two arguments, doing that here requires either matching on a pair, as in Fyodor Soikin's answer, or nested case-expressions:
gridList :: Integer -> Integer -> [(Integer,Integer)]
gridList x y = case x of
1 -> case y of
1 -> [(1,1)]
_ -> helper 1 y
_ -> helper x y ++ gridList (x-1) y
where
helper :: Integer -> Integer -> [(Integer, Integer)]
helper x 1 = [(x,1)]
helper x y = (x,y) : helper x (y-1)
The least invasive workaround is probably using pattern guards:
gridList :: Integer -> Integer -> [(Integer,Integer)]
gridList x y
| 1 <- x, 1 <- y = [(1,1)]
| 1 <- x = helper 1 y
| otherwise = helper x y ++ gridList (x-1) y
where
helper :: Integer -> Integer -> [(Integer, Integer)]
helper x 1 = [(x,1)]
helper x y = (x,y) : helper x (y-1)
As luqui suggests, other options include pulling helper out of the where-clause, and pushing the equations inside it (gridList = go where go 1 1 = [(1,1)] -- etc.).

Instance for function with several classes

I want to realize power function for my custom data type. I mean power (^) which has following signature:
(^) :: (Num a, Integral b) => a -> b -> a
And I mean that my data type MyData should be instance of Num, so I could write
x :: MyData
...
y = x ^ b
where b is some Integral. It's very easy when we need function of one class like
(+), (-), (*) :: (Num a) => a -> a -> a
We just write
instance Num MyData where
(*) x y = someFunc x y
But I have no idea how to define it taking into account that there is also Integral b. That syntax should be like
instance (Integral b) => Num MyData b where
(^) x y = someFunc x y
But I've tried a hundred of such variations and nothing works. Hours of googling also didn't help.
You don't have to do anything to define (^) for your data type; if your type has a Num instance, you get x ^ b for free, because (^) is defined for any type with a Num instance. (It basically just calls * a lot.)
Note that (^) is not a member of Num or Integral; it's just a standalone function whose type is constrained by both classes.
From https://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Real.html#%5E
(^) :: (Num a, Integral b) => a -> b -> a
x0 ^ y0 | y0 < 0 = errorWithoutStackTrace "Negative exponent"
| y0 == 0 = 1
| otherwise = f x0 y0
where -- f : x0 ^ y0 = x ^ y
f x y | even y = f (x * x) (y `quot` 2)
| y == 1 = x
| otherwise = g (x * x) (y `quot` 2) x -- See Note [Half of y - 1]
-- g : x0 ^ y0 = (x ^ y) * z
g x y z | even y = g (x * x) (y `quot` 2) z
| y == 1 = x * z
| otherwise = g (x * x) (y `quot` 2) (x * z) -- See Note [Half of y - 1]
x0 is your MyData value; the only thing (^) ever does with x0 (by virtue of it being passed as the x argument to f or g) is to multiply it by itself, so technically (^) will work as long as you have defined (*) in your Num instance.

How to understand nested lambda functions in Haskell

I am trying to understand the meaning of the following 2 lambda expressions in Haskell:
f = \x -> x (\y -> x y)
g = \x -> (\y -> y) x
I tried to convert them, and I got this:
f x y = x x y
g x y = y x
Is this correct? I assumed the arguments of both functions have to be x and y, as they are both found in a lambda expression in the function description. I basically understood it this way: f(x) = x f(y) and f(y) = y x. And for g, g(x) = g(y) x and g(y) = y. But as I am new to Haskell, I'm not very confident with these types of conversion. If not correct, what would be a correct conversion?
Neither is correct. Your solution uses the functions
f x y = x x y
g x y = y x
which actually mean
f = \x -> (\y -> x x y)
g = \x -> (\y -> y x)
and those differ from the original expressions
f = \x -> x (\y -> x y)
g = \x -> (\y -> y) x
The above two equations can be rewritten as
f x = x (\y -> x y)
g x = (\y -> y) x
But from here, there is no way to turn the remaining lambdas into more arguments for f or g. At best, we can simplify them using beta/eta conversion and get
f x = x x -- eta (\y -> x y) = x
g x = x -- beta (\y -> y) x = x
(Also see the comment below by Will Ness, who points out that through an additional eta expansion in f we could reach the OP's definition. Still, that is incidental.)
Finally, note that Haskell will not accept f x = x x since that can not be typed, unless we use rank-2 types and explicitly provide a type annotation like f :: (forall a. a) -> b. The original code f = \x -> x (\y -> x y) suffers from the same issue. That would also be fine in untyped languages, e.g. the untyped lambda calculus in programming languages theory.
The :type command at the GHCi prompt is your friend. Let's take your second example first
λ> :type let g = \x -> (\y -> y) x in g
let g = \x -> (\y -> y) x in g :: p -> p
So g is well-typed and is a convoluted way to write an identity function :: p -> p. Specifically, g takes some x and applies an identity function (\y -> y) to x, resulting in x. GHCi in giving the type uses a fresh type name p, to avoid confusion. No your g x y = ... is not equivalent. (Check it with :type.)
You can abbreviate :type to just :t. Then let's take your first example.
λ> :t let f = \x -> x (\y -> x y) in f
* Occurs check: cannot construct the infinite type: t2 ~ t2 -> t3
* In the first argument of `x', namely `(\ y -> x y)'
In the expression: x (\ y -> x y)
In the expression: \ x -> x (\ y -> x y)
* Relevant bindings include
x :: t2 -> t3 (bound at <interactive>:1:10)
f :: (t2 -> t3) -> t3 (bound at <interactive>:1:5)
Errk. Is your suggested f the same as that?
λ> :t let f x y = x x y in f
* Occurs check: cannot construct the infinite type:
t3 ~ t3 -> t4 -> t5
* In the first argument of `x', namely `x'
It at least looks like a similar error message. What are these t2, t3, t4, t5? Again it's GHCi using fresh names for the types, to avoid confusion.
Looking at the let f = ..., GHCi sees x is applied to something, so it gives x :: t2 -> t3 where t2 is the type of its argument, t3 is the return type. It also sees f = \x -> x (blah). So the return type of f must be whatever x returns, i.e. t3, and the argument to f is x. So f :: (t2 -> t3) -> t3.
Inside the (blah), there's x applied to something. So the something (i.e. y) must be the type of x's argument, and the return type must be x's return type. I.e. (\y -> x y) :: t2 -> t3. Errk: then we must have x's argument type same as that, because x is applied to it. And the way we write 'same as' is with ~.
Then the error message tells you GHCi is trying to make sense of t2 ~ (t2 -> t3). (-> binds tighter than ~.) And if you try to subsitute that equivalence for t2 into the RHS you'll get t2 ~ (((... -> t3) -> t3)-> t3) ad infinitum.
Your suggested equivalent for f x y = is not equivalent (the message/typing is a little different). But they're both infinite types, so not allowed.

Recursive functions with multiple arguments Haskell

A really simple question: I want to implement the multiplication of 2 integers in Haskell.
What I wrote doesn't compile:
mult :: Int -> Int -> Int
mult x 1 = x
mult 1 y = y
mult x y = x + (mult x-1 y)
The problem is the last statement. I've tried writing it as:
mult x y = x + (mult x-1 y)
and also
mult x y = x + (mult(x-1,y))
The error I get is:
Couldn't match expected type `Int' with actual type `Int -> Int'
In the return type of a call of `mult'
I don't know why the compiler would say that mult returns an Int -> Int when it clearly returns an Int.
You have to put x-1 into brackets! Like so
mult x y = x + (mult (x-1) y)
By the way, this does not compute the multiplication of x and y :-)
Try some examples... it's a little mistake only.
In
mult x y = x + (mult x-1 y)
the expression within the parentheses parses as:
(mult x) - (1 y)
And so the compiler thinks the first argument to (-) is mult x, which is an Int -> Int function because just one argument (rather than two) is being passed. Instead, you want:
mult x y = x + mult (x-1) y
It's a simple parser issue. The compiler is reading mult x-1 y as ((-) (mult x) y) when what you mean is mult (x-1) y. Function application binds very tightly in Haskell, so it's sometimes better to use too many parentheses rather too few, especially while you're still learning the basics of the language.
The error occurs because the type of (mult x) is Int -> Int but the type of y is Int, and you can't subtract those two things.

Resources