Haskell - fast naming of projection functions - haskell

Suppose I want to define a function f in terms of some other predefined function g as follows:
f :: Int -> Int -> Int
f 2 b = g b
f _ _ = 1
That is, I want to define the projection, f(2,_) : Int->Int to be the same as g(_) : Int->Int. Gladly, Haskell has first class functions, and so definitions like the following squarePlusOne are valid and standard:
plusOne :: Int -> Int
plusOne i = i+1
square :: Int -> Int
square i = i*i
squarePlusOne :: Int -> Int
squarePlusOne = plusOne . Square
With Haskell's currying (ie. f takes just one Int as input and returns an (Int->Int) typed function), I am surprised I cannot write
f 2 = g
Why not? Or is there some other syntax?

Indeed, writing f 2 = g is a valid way to define f. However, when defining functions in this way, remember you must define the whole function with the same pattern signature. That is, you may not exhaust your function by writing
f 2 = g
f i j = i+j
Instead, this may be achieved like so:
f 2 = g
f i = (\j-> i+j)

You can use the const function, which creates a function that ignores its argument to return a fixed value.
f :: Int -> Int -> Int
f 2 = g -- f 2 x = g x
f _ = const 1 -- f _ x = const 1 x == (\_ -> 1) x == 1

Related

How to pass not a function that returns a boolean in another function?

I want to negate a function in the if clause of another function like bellow:
isBig :: Integer -> Bool
isBig n = n > 9999
function :: Integer -> Integer
function n =
if not isBig n then ... else ...
It complies when it's just 'if isBig n then else' but I'm not sure why it doesn't work for 'not isBig' as I get this error:
*Couldn't match expected type Bool' with actual type Integer -> Bool'
Many thanks in advance.
You want not (isBig n). not isBig n tries to pass two arguments to not, both isBig and n. isBig is an Integer -> Bool but a Bool is expected, hence the error.
In general, function application in Haskell is left-associative, meaning that an expression like this:
f 2 3 5
Is parsed like this:
(((f 2) 3) 5)
Likewise, the arrows in function types are right-associative, so for example if we had this definition for f:
f :: Int -> Int -> Int -> Int
f x y z = x * y + z
That type signature is the same as:
f :: Int -> (Int -> (Int -> Int))
So it looks like this as you apply more arguments:
f :: Int -> (Int -> (Int -> Int))
(f 2) :: (Int -> (Int -> Int))
((f 2) 3) :: (Int -> Int)
(((f 2) 3) 5 :: Int
==
f :: Int -> Int -> Int -> Int
f 2 :: Int -> Int -> Int
f 2 3 :: Int -> Int
f 2 3 5 :: Int
When you’re applying a chain of functions to an argument, you end up with parentheses associating to the right:
f (g (h x))
In this case it’s common to use the $ operator, which is right-associative and has low precedence, just to reduce the nesting of brackets:
f $ g $ h x
And you can do so in your case: not $ isBig n
You can also use composition to factor out the chain of functions and apply it to different arguments elsewhere:
fgh = f . g . h
fgh x
==
(f . g . h) x
==
f (g (h x))
isNotBig = not . isBig
isNotBig n
==
(not . isBig) n
==
not (isBig n)

How to fix "Illegal type signature" error in Haskell

I ran into the following error in Haskell:
"Type signatures are only allowed in patterns with ScopedTypeVariables"
How should I re-use the defined variables. Thanks in advance
sum :: (Double -> Double) -> (Double -> Double) -> Int ->
(Double -> Double)
sum f g n = (\x -> helper f g n x)
where
helper :: (Double -> Double) -> (Double -> Double) -> Int -> Double ->
Double
|n == 0 = 0
|mod n 2 == 1 = f(x) + helper f g n-1 f(x)
|otherwise = g(x) + helper f g n-1 g(x)
This actually looks more like a syntactical error: you never defined a function body for helper, indeed you defined the signature of helper, followed by guards (the | ... part), but you should again state helper f g n x = ....
Furthermore I don't think it is useful to define helper here with a variable for f, an g, since these remain fixed throughout the recursion.
You can probably define the function as:
sumfg :: (Double -> Double) -> (Double -> Double) -> Int -> Double -> Double
sumfg f g = helperf
where helperf 0 _ = 0
helperf i x = let fx = f x in fx + helperg (i-1) fx
helperg 0 _ = 0
helperg i x = let gx = g x in gx + helperf (i-1) gx
We here defined two "helper" functions helperf and helperg, helperf will sum up f x with helperg (i-1) (f x), and helperg does the same, except that we use g instead of f. We here thus use mutual recursion to solve the problem.
We can however solve this problem more elegantly, by making use of scanl :: (b -> a -> b) -> b -> [a] -> [b], take :: Int -> [a] and sum :: Num a => [a] -> a:
sumfg :: Num a => (a -> a) -> (a -> a) -> Int -> a -> a
sumfg f g n x = sum (take n (scanl (flip ($)) (f x) (cycle [g, f])))
Here we thus make an infinite list of g and f, like [g, f, g, f, g, f, ...] with cycle [f, g]. We then use scanl (flip ($)) to each time apply the accumulator to one of the functions, and yield that element. We take the first n items of that list with take n, and finally we use sum to sum up these values.
For example:
Prelude> sumfg (2+) (3*) 5 1
91
Since (2+1) + (3*(2+1)) + (2+(3*(2+1))) + (3*(2+(3*(2+1)))) + (2+(3*(2+(3*(2+1))))) is 91.
We also generalized the signature: we can now work with any numerical type a, with the two functions f and g of type f, g :: a -> a.

How to create an fmap that can take a tuple of functions instead of just a single function?

This could be a way of constructing
Is there a (ideally standard) way of accomplishing
f :: Int -> Int
f x = 2*x
g :: Int -> String
g x = show x
h = (f, g)
fmap h 5 -- results in: (10, "5")
In general, for functions going from A->T_i for some variable types T_i and a fixed type A, I think this would just be a simplification of a BiFunctor, at lease for a 2-tuple of 1-argument functions - it would be great to see a generalization going beyond 2-tuples.
You could use uncurry (&&&), as follows:
> import Control.Arrow
> f :: Int->Int ; f x = 2*x
> g :: Int->String ; g x = show x
> h = (f, g)
> uncurry (&&&) h 5
(10,"5")

Pattern matching against Just containing a pair

I'm experimenting with Haskell and I'm wondering why I couldn't match against a Just containing a pair. I have little experience with this language and I'm completely lost.
f :: Int -> Maybe (Int, [Int])
f 100 = Nothing
f x = Just (x,[x])
g :: Int -> Maybe Int
g x
| u==Nothing = Nothing
| u==(Just (r,s)) = Just r
where
u=f x
So what is wrong with this code. GHC says that r and s are not in scope.
If you want to pattern match in a guard, you have to use a pattern guard:
g :: Int -> Maybe Int
g x
| Just (r,_) <- u = Just r
| otherwise = Nothing
where
u = f x
After all, (==) is a regular function, you need values on both sides to use it. Since r and s aren't known in u == Just (r,s), the compiler gives you your error message.
By the way, taking a Maybe and return Nothing if the value was Nothing or Just (h x) for a function h and Just x is so common, it forms a pattern: fmap. You can write
g :: Int -> Maybe Int
g x = fmap fst (f x)
Because the guard expression can't do pattern matching.
Guard expression is just like a boolean expression, it can't do binding. It just uses the binding before |, in this case x.
So working solution will be like this.
g :: Int -> Maybe Int
g x = case f x of
Nothing -> Nothing
Just (r,_) -> Just r
You can use case expressions
g :: Int -> Maybe Int
g x =
case f x of
Nothing -> Nothing
Just (r,s) -> Just r

Writing in pointfree style f x = g x x

I am learning Haskell. I'm sorry for asking a very basic question but I cant seem to find the answer. I have a function f defined by :
f x = g x x
where g is an already defined function of 2 arguments. How do I write this pointfree style?
Edit : without using a lambda expression.
Thanks
f can be written with Control.Monad.join:
f = join g
join on the function monad is one of the primitives used when constructing point-free expressions, as it cannot be defined in a point-free style itself (its SKI calculus equivalent, SII — ap id id in Haskell — doesn't type).
This is known as "W" combinator:
import Control.Monad
import Control.Monad.Instances
import Control.Applicative
f = join g -- = Wg (also, join = (id =<<))
= (g `ap` id) -- \x -> g x (id x) = SgI
= (<*> id) g -- = CSIg
= g =<< id -- \x -> g (id x) x
= id =<< g -- \x -> id (g x) x
S,K,I are one basic set of combinators; B,C,K,W are another - you've got to stop somewhere (re: your "no lambda expression" comment):
_B = (.) -- _B f g x = f (g x) = S(KS)K
_C = flip -- _C f x y = f y x = S(S(K(S(KS)K))S)(KK)
_K = const -- _K x y = x
_W = join -- _W f x = f x x = CSI = SS(KI) = SS(SK)
_S = ap -- _S f g x = f x (g x) = B(B(BW)C)(BB) = B(BW)(BBC)
= (<*>) -- from Control.Applicative
_I = id -- _I x = x = WK = SKK = SKS = SK(...)
{-
Wgx = gxx
= SgIx = CSIgx
= Sg(KIg)x = SS(KI)gx
= gx(Kx(gx)) = gx(SKgx) = Sg(SKg)x = SS(SK)gx
-- _W (,) 5 = (5,5)
-- _S _I _I x = x x = _omega x -- self-application, untypeable
-}
I got here by pure chance, and I want to offer my solution, as nobody has mentioned lifting yet in this thread, not explicitly at least.
This is a solution:
f = liftM2 g id id
How to look at it?
g has type a -> a -> b, i.e. it takes two values of some type (the same type for both, otherwise the definition the OP gave of f wouldn't make sense), and gives back another value of some type (not necessarily of the same type as the arguments);
lift2M g is the lifted version of g and it has type (Monad m) => m a -> m a -> m b: it takes two monadic values, which are each a value in a so-far-unspecified context, and gives back a monadic value;
when passing two functions to liftM2 g, the die is cast on what the context of the Monad is: it is that the values are not in there yet, but will eventually be, when the function will receive the arguments it needs; in other words, functions are monads that store their own future values; therefore, lift2M g takes in input two functions (or, the future values of two functions), and gives back the another function (or, its future value); knowing this, its type is the same as above if you change m to (->) r, or r ->: (r -> a) -> (r -> a) -> (r -> b)
the two functions that we pass are both id, which promises it'll give back the same value it receives;
liftM2 g id id is therefore a function of type r -> b that passes its argument to those two ids, which let it unchanged and forward it to g.
In a similar fashion, one can exploit that functions are applicative functors, and use this solution:
f = g <$> id <*> id

Resources