I'm trying to get a grip on how tuples work in Haskell.
I came across this type constructor leftRight :: (Either a b -> c) -> (a -> c, b -> c) and I'm struggling to see what it does.
So we have (Either a b -> c)which means that either a is applied to c or b is applied to c. But the output is a tuple?
Does that mean that it splits the function so that left side of the tuple takes in argument given at a and right side takes argument given at right?
How would this look in code?
"I came across this type constructor..."
It's not a type constructor - it's a function type declaration.
The -> separates out the parameter types. The final one is the return type, and the previous ones are the input types.
Hence leftRight :: (Either a b -> c) -> (a -> c, b -> c) takes one input and returns one output.
Input function: (Either a b -> c)
Output function pair: (a -> c, b -> c)
The parentheses contain the functions.
The first function takes an Either type (left value is the error type, a, and the right value is the OK type, 'b' - it helps me to think of the latin, sinister for left, and dexter for right - your mileage may vary) as the input and returns something of type c.
The second function comes as a tuple of two separate functions, one is a -> c, and one is b -> c.
A concrete version: type a is a String to contain my error message, type bis an Int, and type c is another string.
leftRight :: (Either String Int -> String) -> (String -> String, Int -> String)
So we have Either a b -> c which means that either a is applied to c or b is applied to c
Wrong, or at least badly worded. Nothing is “applied to c” here.
What it actually means is: the function can accept an a-value or a b-value, and in either case produces a c-value.
This is equivalent to having both a function that accepts only a-values and gives c-results, and one that accepts only b-values and gives c-results. The tuple groups both of these functions together.
It might help to look at an example to illustrate:
fryPancake :: Either Butter Margarine -> Pancake
[Assume we've already taken care of the flour, eggs etc. in the batter]
From this you can obtain both
fryPancakeWithButter :: Butter -> Pancake
fryPancakeWithButter b = fryPancake (Left b)
fryPancakeWithMargarine :: Margarine -> Pancake
fryPancakeWithMargarine m = fryPancake (Right m)
Now you just group both of these together:
fryPancake' :: (Butter -> Pancake, Margarine -> Pancake)
fryPancake' = (fryPancakeWithButter, fryPancakeWithMargarine)
...which is the same as
fryPancake' = leftRight fryPancake
The input to leftRight is a function and the output is two functions. The tuple is barely relevant, except that it groups the two functions together into a single output, so leftRight can return both of them at once.
One function's type is a -> c and the other one's type is b -> c. Presumably, the first function wraps the a in Left and then calls the original function, and the second one wraps the b in Right and then calls the original function:
leftRight :: (Either a b -> c) -> (a -> c, b -> c)
leftRight original = (leftFunc, rightFunc)
where
leftFunc aVal = original (Left aVal)
rightFunc bVal = original (Right bVal)
The key is to use function composition. A function of type a -> c can be created from functions of type a -> Either a b and Either a b -> c. You have Left :: a -> Either a b and you have the argument f :: Either a b -> c passed to leftRight.
The same argument lets you construct a function of type b -> c similarly. This gives you
leftRight :: (Either a b -> c) -> (a -> c, b -> c)
leftRight f = let g1 = ...
g2 = ...
in (g1, g2)
I leave the definitions of g1 and g2 as an exercise.
Related
I need to define a Union Type which the set of the type includes
a -> b OR a -> IO b
a -> b || a -> IO b
or
a -> b | IO b
foo :: (a -> b | IO b) -> IO (R a) -> IO (R b)
I tried data unionType b = b | IO b that does not work.
Not a data constructor: ‘b’parser
No quick fixes available
Is it possible in Haskell?
In Haskell, a sum type (the standard term for a disjoint union type) requires explicit "constructors" for its components, so you need to write something like:
data BarType b = BarPure b | BarIO (IO b)
This defines a type BarType, and it also defines constructors BarPure and BarIO for use in constructing values of this type:
val1, val2 :: BarType String
val1 = BarPure "pure"
val2 = BarIO getLine
and consuming values of this type via case-matching:
runBar :: BarType b -> IO b
runBar barb = case barb of
BarPure s -> pure s
BarIO act -> act
There are two issues: On the one hand your type must be upper-case, that is UnionType. Second, you need to define type constructors to be able to create a value of said data type. So the closest would be e.g.
data UnionType b = Left b | Right (IO b)
Here I chose the arbitrary names Left and Right for the constructors, but you can use any you like.
If the Left/Right constructors seem familiar to you, that is because Either uses these by default, and can do exactly the same with a slightly "cheaper" type synonym:
type UnionType b = Either b (IO b)
Of course in both cases we have to deconstruct the type to get to the actual values of b and IO b.
EDIT: As #leftroundabout mentioned, it is not very convenient to define a data type with type constructors called Left and Right, as these constructors are already used with the built in Either.
something :: a -> (a -> ())
Is there a name/concept for something, the function that takes an a and returns a function from a to unit?
That is given an a, it returns a sink/consumer of a?
Is something just a -> a -> (), a bi-consumer of a?
.
What about:
somethingElse :: a -> (a -> a)
the function from a to a function from a to a?
somethingElse is basically a combiner or binary operator on a, a -> a -> a, right?
All possible implementations of something are equivalent to
sink :: a -> a -> ()
sink x y = ()
which you could also write as
sink = const $ const ()
As you can imagine, this is not a very frequently used function (it is guaranteed to never do anything interesting), and so there is no special name for it.
Your second question, about a -> a -> a, is more interesting. If the function is to be polymorphic, i.e. to work over any a at all, there are just two possible implementations:
first x y = x
second x y = y
But this type can be specialized to do something interesting for more specific a types.
(+) :: Int -> Int -> Int
is one example of such a specialization. Indeed this is the type of a binary operator, and any binary operator taking and returning a values has this type, or a specialization of it.
Functions of this type are related to Monoid and to Semigroup, in a way, but not all such functions meet the rules necessary to be part of a Monoid or Semigroup instance.
Studying Haskell first principles. Absolute beginner in Haskell.
If:
data A
data B
func :: A -> B
func = undefined
What would the actual function be? Worked though load of exercises with great result (also thanks to you) but again I am stuck. Does A -> B indicate two different types like 'String' -> 'Char'? Just trying to wrap my head around it.
No, (concrete) types start with an Uppercase. So A -> B means the types A and B you have defined (well not defined here) with your data A = ... expressions, like for instance:
data A = Foo | Bar Int | Qux String A
In case the signature contains an identifier with a lowercase, it is a type variable. For instance foo :: a -> b, means a and b can be substuted by any type. So foo is a function that can be A -> B, but also A -> Int, Char -> B, and Char -> Int.
You can also add type constraints to the signature to restrict the types for which for instance a and b can be used. Like foo :: (Show a, Num b) => a -> b restricts a and b, such that there should exist an instance Show a and instance Num b for the types a and b such that foo is defined over these types.
Thanks Willem, Chepner. Your answers helped me out to conjure up:
data A
data B
funcAJ :: A -> B
funcAJ a = a
where a = b
b = undefined
This typechecks as funcAJ :: A -> B, which I understand. Thanks so much!
I'm still a beginner when it comes to Haskell syntax and functional programming languages so when I look at the type declaration for Data.Function.on which is on :: (b -> b -> c) -> (a -> b) -> a -> a -> c, my interpretation is that it takes four parameters: (b -> b -> c), (a -> b), a, a, and returns c. However, when I look at the general use syntax for Data.Function.on which is (*) `on` f = \x y -> f x * f y, it is only taking two function parameters, not four, so how does the type signature relate to the usage syntax?
my interpretation is that it takes four parameters
All Haskell functions take one argument. Some of them just return other functions.
The best way to look at the signature for on is as a higher-order function: (b -> b -> c) -> (a -> b) -> (a -> a -> c). This says "if you give me a binary operator that takes bs and gives a c and a way to get bs from as, I will give you a binary operator that takes as and gives a c". You can see this in the definition:
(*) `on` f = \x y -> f x * f y
The Haskell arrow for function types hides a simple but clever idea. You have to think of -> as an operator, like + and -, but for types. It takes two types as arguments and gives you a new type consisting of a function. So in
Int -> String
You have the types Int and String, and you get a function from an Int to a String.
Just like any other operator, you need a rule for a chain of them. If you think of -, what does this mean?
10 - 6 - 4
Does it mean (10 - 6) - 4 = 0, or does it mean 10 - (6 - 4) = 8? The answer is the first one, which is why we say that - is "left associative".
The -> operator is right associative, so
foo :: Int -> String -> String
actually means
foo :: Int -> (String -> String)
Think about what this means. It means that foo doesn't take 2 arguments and return a result of type String, it actually takes 1 argument (the Int) and returns a new function that takes the second argument (the String) and returns the final String.
Function application works the same way, except that is left associative. So
foo 15 "wibble"
actually means
(foo 15) "wibble"
So foo is applied to 15 and returns a new function which is then applied to "wibble".
This leads to a neat trick: instead of having to provide all the parameters when you call a function (as you do in just about every other programming language), you can just provide the first one or the first few, and get back a new function that expects the rest of the parameters.
This is what is happening with on. I'll use a more concrete version where 'f' is replaced by 'length'.
(*) on length
you give on its first two parameters. The result is a new function that expects the other two. In types,
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
In this case (*) has type Num n => n -> n -> n (I'm using different letters to make this less confusing), so that is matched with the type of the first argument to on, leading to the conclusion that if type b is substitued by n then type c must be as well, and and must also be a Num instance. Therefore length must return some numeric type. As it happens the type of length is [d] -> Int, and Int is an instance of Num, so that works out. So at the end of this you get:
(*) `on` length :: [d] -> [d] -> Int
As an intuitive aid, I read this as "if you give me a comparator of type b, and a way to extract values of type b from values of type a, I will give you a comparator of type a".
E.g. if a is some composite data type and b is some numerical attribute of these data values, you can express the idea of sorting these composite data types by using Data.Function.on.
I'm having some trouble understanding, how this type declaration works.
The type is: (a -> b) -> (b -> c) -> (c -> d) -> a -> d
So, to me I interpret this as a function that takes a function and that function takes another function which outputs a value d.
So, this is how I make my function:
Example :: (a -> b) -> (b -> c) -> (c -> d) -> a -> d
Example f g h x = f ( g ( h (x) )
I'd really appreciate it, if you guys could help me clarify. Thank you!
I think that you already know the theory behind the type you're writing, so I'll try to inject some intuitive way to read it (at least I hope so, your question is not totally clear to me).
When you read something like (a -> b) inside a type, that's a function, as you said. For example (Int -> Bool) is a function.
Let's make an example:
even :: Int -> Bool -- A more generic version of that is in the Prelude
even n = n `rem` 2 == 0
filter :: (Int -> Bool) -> [Int] -> [Int] -- And of that, too
filter _ [] = []
filter f (x:xs)
| f x = x : filter f xs
| otherwise = filter f xs
filteredEven :: [Int]
filteredEven = filter even [1..5] -- it gives [2, 4]
In this example we have a "high order function", a function that get another function and use it in some way.
In a function like the one you're defining you simply use 3 functions (and another parameter). But you can know more.
Each function you declare in the type accept a value returned from the previous one. So a possible solution is the one you have already showed. But the types are generic. There is not a total function that returns a generic value (where total means that it terminate always returning a value different from bottom if all the values are total and different by bottom, so it don't crash or return undefined, for example). So, if you wants a total function you have to have a way to generate the variables requested, from the context of the function (their parameters).
In the example before, using the names used by you, you have to return a value of type d. You only have a way to produce a value of that type, the h function. But to use the h function you have to get a value of type c. You only have the g function for that. But you need a value of type c. Fortunately you have the function f, that in exchange of a value of type a returns the value needed. We have this value (and don't have any other way to obtain a value of that type), so the function can be written. We can't in any way alter the values obtained (call multiple times the functions don't work, for purity and the fact that we have only a way to produce the values), so that's the only way to construct the function, if we wants it to be total:
Example (a -> b) -> (b -> c) -> (c -> d) -> a -> d
Example f g h x = h (g (f x)))
We can write the function in many other ways, but the results they give will be always the same (if Example, f, g and h are total and x is not bottom). So the type can express really well the function, because we can understand how the function works only looking at the type!