Im trying to understand Haskell and I have a question: What is the type of this function and how do you call it.
two f(a,b) = f a b
If we take, for example, arguments of type Int, then the type of two is like this:
two :: (Int -> Int -> Int) -> (Int, Int) -> Int
two f (a,b) = f a b
example:
two (*) (3,4)
12
Explanation:
You are taking a function that takes 2 arguments (Int -> Int -> Int)and a tuple (Int, Int) and applying that function to a and b.
The actual type, when not constrained, is actually like this:
:t two
two :: (t1 -> t2 -> t) -> (t1, t2) -> t
So for example other things are possible:
two (++) ("he","llo")
"hello"
(etc etc.)
Related
I have the following two type signatures in Haskell:
foo :: (a -> (a,b)) -> a -> [b]
bar :: (a -> b) -> (a -> b -> c) -> a -> c
I want to write a concrete implementation of these two functions but I'm really struggling to understand where to start.
I understand that foo takes a function (a -> (a,b)) and returns a and a list containing b.
And bar takes a function (b -> c) which returns a function (a -> b -> c) which finally returns a and c.
Can anyone show me an example of a concrete implementation?
How do I know where to start with something like this and what goes on the left side of the definition?
You have some misunderstandings there:
I understand that foo takes a function (a -> (a,b)) and returns a and a list containing b.
No, it doesn't return a. It expects it as another argument, in addition to that function.
And bar takes a function (b -> c) which returns a function (a -> b -> c) which finally returns a and c.
Same here. Given g :: a -> b, bar returns a function bar g :: (a -> b -> c) -> a -> c. This function, in turn, given a function h :: (a -> b -> c), returns a function of type a -> c. And so it goes.
It's just like playing with pieces of a puzzle:
foo :: (a -> (a,b)) -> a -> [b]
-- g :: a -> (a,b)
-- x :: a
-- g x :: (a,b)
foo g x = [b] where
(a,b) = g x
bar :: (a -> b) -> (a -> b -> c) -> a -> c
-- g :: a -> b
-- x :: a
-- g x :: b
-- h :: a -> b -> c
-- h x :: b -> c
-- h x (g x) :: c
bar g h x = c where
c = ....
There's not much free choice for us here. Although, there are more ways to get more values of type b, for foo. Instead of ignoring that a in (a,b) = g x, we can use it in more applications of g, so there actually are many more possibilities there, like
foo2 :: (a -> (a,b)) -> a -> [b]
foo2 g x = [b1,b2] where
(a1,b1) = g x
(a2,b2) = g a1
and many more. Still, the types guide the possible implementations. foo can even make use of foo in its implementation, according to the types:
foo3 :: (a -> (a,b)) -> a -> [b]
foo3 g x = b : bs where
(a,b) = g x
bs = ...
So now, with this implementation, the previous two become its special cases: foo g x === take 1 (foo3 g x) and foo2 g x === take 2 (foo3 g x). Having the most general definition is probably best.
In addition to #will-nes's answer, it will be useful to treat (->) as a right-associative infix operator. So something like f: a -> b -> c is the same as f: a -> (b -> c). So this is saying f is a function that takes a value of type a and returns you a value of type b -> c, which is, another function, one that takes a value of type b and returns you a value of type c.
So the types in your example can be re-written as follows
foo :: (a -> (a,b)) -> (a -> [b])
bar :: (a -> b) -> ((a -> (b -> c)) -> (a -> c))
Similarly, you can think of arguments to a function in pieces as well, as being left-associative (like + and -), though there's no explicit operator in this case. foo a b c d e is the same as ((((foo a) b) c) d) e. For example, let's say we have a function f: Int -> Int -> Int (which is the same as f: Int -> (Int -> Int)). You don't have to provide both arguments at once. So you can write g = f 1, which has the type (Int -> Int). And then you can provide an argument to g, like g 2, which has the type Int. f 1 2 and let g = f 1 in g 2 are more or less the same. Here's a more concrete example of how this works:
Prelude> f = (+)
Prelude> g = f 1
Prelude> g 2
3
Prelude> :t f
f :: Num a => a -> a -> a
Prelude> :t g
g :: Num a => a -> a
Prelude> :t g 2
g 2 :: Num a => a
In #will-nes's sample implementation examples, he defines the functions with all of the arguments up front, but you don't have to think of them that way. Just think of f: a -> b -> c as taking a value of type a and returning another function. While most of the methods you encounter will use all of their arguments up-front, there might be cases in which you don't want to do that. Here's an example:
veryExpensive :: A -> B
unstagedFun :: A -> (B -> C) -> C
unstagedFun a f = f (veryExpensive a)
stagedFun :: A -> (B -> C) -> C
stagedFun a = let b = veryExpensive a in \f -> f b
(You can also rewrite the latter as let b = veryExpensive a in ($ b))
Of course, with compiler optimizations, I wouldn't be surprised if the unstaged version staged automatically, but hopefully this offers some motivation for thinking of functions as not having multiple arguments, but rather, as a single argument, but they may return other functions that may themselves return functions (but also only take a single argument).
I'm doing a school assignment in OCaml and I had a question regarding the meaning of an expression.
When defining function if I, for example, wrote:
let iter : int * (int -> int) -> (int -> int)
= fun (n,f) ->
What does (int -> int) mean? I understand the function itself receives a pair as an argument, but I don't fully understand what the parentheses mean...
The parentheses are there to disambiguate between a function of type (int -> int) - meaning it takes in a parameter of type int and returns an int - and possibly just two regular ints taken as parameters of that function. Without the first pair of parentheses for example, your iter would expect an(int, int) tuple, and in case no other parameter is present, expect an int -> int -> int as return type.
Note that the second pair of parentheses is not strictly necessary, but it can be a good indicator that you are expecting a function in return. Without that pair of parentheses, the function can be read as expect a tuple of (int, int -> int) plus another int, returning an int for example.
An example of a function with the same signature as your iter could be:
let random_func: int * (int -> int) -> (int -> int) =
fun (n, f) -> f
Find TL;DR below.
In lambda calculus (please bear with me), which is what ML-languages are rooted from, the core idea is all about abstracting an application or mapping of function to an argument. Only one argument.
λx[x + 1]
The λ in the above reads abstracting function x + 1 into an application waiting for a value for x, guard it from changing, and apply (replace the x in the function with the value and calculate).
The above in Ocaml would be equivalent to:
fun x -> x + 1
which has the type int -> int, or input type int and output type int. Now, lambda only deals with one argument at a time. How does that work with functions with multiple arguments like x*x -2*x + c (a polynomial function x2 − 2·x + c)? It evaluates the argument one at a time just like before.
λc[λx[x*x - 2*x + c]]
Thus, the output of the previous application becomes the input of the next one, and so on. The Ocaml equivalent would be
fun c x -> (x * x) - (2 * x) + c
The function has type int -> int -> int or (int -> int) -> int (chain of input -> output) If you apply the function partially to an argument x = 3, you get a reduced function like so:
fun c 3 -> (3 * 3) - (2 * 3) + c
fun c -> 9 - 6 + c
fun c -> 3 + c
at which the resulting function would have the type of int -> int. This is the basis of currying. It might look confusing at first, but it proves to be very useful and under-appreciated in imperative languages. For instance, you could do something like this:
let waiting_for_c_and_x = fun c x -> 2*x + c
let waiting_for_c = waiting_for_c_and_x 10 in
let result = waiting_for_c 2 (* result = 22 *)
TL;DR
However, using parentheses to group these chains of inputs/outputs are tricky but necessary in Ocaml because in reality the compiler cannot guess from e.g. int * int -> int if you mean an application that accepts an int * int pair as an input and return an int as an output (which we could parenthesize as (int * int) -> int) or one that accepts a pair of int and a function of type int -> int as argument (which could be written as int * (int -> int)).
Applied from Stanford Encyclopedia of Philosophy (very good read)
As the questions states, I am having a little trouble with defining a function with parameters different types. (array of Num, two parameters Int and returning Int).
This is function title:
_sum_divide :: (Num a) => [a] -> (Int b) => b -> b -> b
And I get this error I cannot figure out
`Int' is applied to too many type arguments
In the type signature for `_sum_divide':
_sum_divide :: Num a => [a] -> Int b => b -> b -> b
Sorry for the silly error, I am a noob with Haskell.
Thanks, have a good day/evening.
This seems to be a basic confusion between the concepts of type classes and of types. OO languages throw these all together, but in Haskell they are fundamentally different things.
A type is a set† of values. For example, the type Bool contains the values False and True. The type Int contains the values 0, 1 ... 9223372036854775807 and their negatives.
A type class is a set of types. For example, the class Num contains the type Int, the type Double, the type Rational... and whatever type T of your own, if you just define an instance Num T.
Generally, types are used in function signatures just by naming them. For instance,
foo :: [Int] -> [Int]
foo = map (*3)
is a function accepting a list of Int numbers (i.e. values of type Int), and gives another such list as the result (wherein each entry is tripled).
There is no constraint at all in the signature of foo. I could actually add one, like
foo :: Num Int => [Int] -> [Int]
This would express that the function needs Int to be an instance of the Num class to work. Well, it does need that in order to be able to calculate *3, but the constraint is superfluous, because we know that Int is a Num instance, the compiler doesn't just forget about that.
Where constraints are really useful is in polymorphic functions. For example, the following function triples every entry in a list of numbers, and doesn't care what particular type the numbers have:
foo :: Num n => [n] -> [n]
foo = map (*3)
This notation with type variables like a is actually shorthand for
foo :: ∀ n . Num n => [n] -> [n]
meaning, for all numerical types n, the function foo maps lists of n-values to lists of n-values.
It's important that constraints are completely separate‡ from the actual type specification in a signature. For instance, to specify for a polymorphic function [a] -> b -> b -> b that a should be a Num instance and b an Integral instance (the class of whole-number types, containing amongst other Int), you'd write
sum_divide :: (Num a, Integral b) => [a] -> b -> b -> b
Alternatively, if you really mean Int – that's just a single type, no reason to introduce a type variable for it.
sum_divide :: Num a => [a] -> Int -> Int -> Int
...although, you can still introduce the b variable if you like. You'll need an equational constraint (those are basically ad-hoc type classes containing only a single type)
{-# LANGUAGE TypeFamilies #-}
sum_divide :: (Num a, b ~ Int) => [a] -> b -> b -> b
†Mathematicians would object about several levels of differences between types, sets and classes. Read my notion of “set” as just “collection of things”.
‡In more complicated settings you can actually mix constraints and types, but that's advanced stuff.
The signature for a function that takes list of Nums and 2 int, and returns an int is:
_sum_divide :: (Num a) => [a] -> Int -> Int -> Int
The part before the thick arrow specifies the constraints. The part after it is where you use the constraints.
You had 2 main issues:
There should only 1 list of constraints in a signature.
Int isn't a Typeclass. (Num a) means a can be any type that supports the Num Typeclass. Int however is a concrete type, not a Typeclass, so (Int b) doesn't make sense.
I want to be able to make operators such as found in VB(.net) like shown below
Console.WriteLine ( 16 Mod 2 )
produces an output shown below
0
As you can see, this makes code slightly easier to read. How would I go about making functions that do this?
I have tried the following format
equal :: Integer -> Integer -> bool
x `equal` y = x == y
and I get the following error
*Main> 5 equal 5
<interactive>:1:1: error:
* Non type-variable argument
in the constraint: Num ((Integer -> Integer -> Bool) -> t -> t1)
(Use FlexibleContexts to permit this)
* When checking the inferred type
it :: forall t t1.
(Num ((Integer -> Integer -> Bool) -> t -> t1), Num t) =>
t1
*Main>
What is going wrong and how do I do it correctly?
You need to use backticks around equal when you call it, exactly as you did to define it.
5 `equal` 5
The way you wrote it, Haskell thinks you're trying to pass equal as an argument to 5, rather than the other way around.
I've defined a function f1 and f2,so that I can use at the and the function composition (fkomp), which is supposed to use f1 and f2 to calculate 2^x by every element in a given List.
f1 :: Int -> Int
f1 x = product (replicate x 2)
f2 :: (a -> b) -> [a] -> [b]
f2 f xs = [f x | x <- xs]
fkomp :: [Int] -> [Int]
fkomp xs = f2 f1 $ xs
It works,but the problem is,that i can't write my code with composition:
fkomp xs = f2.f1 $ xs
I've been typing every single combination but it doesn't work with composition.
Could someone lighten my path ?
Thanks a lot
Ok, let's look just at the types (it's like a puzzle - the types have to fit):
f1 :: Int -> Int
f2 :: (a -> b) -> [a] -> [b] = (a -> b) -> ([a] -> [b])
in order to compose the both you need ones co-domain to be the same as the others domain.
This is because the composition has type:
(.) :: (b -> c) -> (a -> b) -> a -> c
See the b has to fit ;)
So for your f1 and f2 you would need either Int ~ (a -> b) or Int ~ ([a] -> [b]) both of which are not working well (as you found out).
BUT you kind of have the ability to apply f1 to f2 as f1 just fits f2 first argument (as you have seen too) - so I am a bit confused why you even want to use composition here.
remarks
your functions are a bit strange - I think the usual way to write them would be
f1 x = 2 ^ x
f2 = map
or even
fkomp :: [Int] -> [Int]
fkomp = map (2^)
note that the last one is not function-composition but (just as your case) function-application: I apply the function (2^) :: Int -> Int to map :: (Int -> Int) -> [Int] -> [Int] and get a function of type [Int] -> [Int] as the result (if you check the types in GHCi you will see a more generic versions but I think this is a bit more clear)