Is there anything similar to Haskell’s `$` in Unison? - unison-lang

In Haskell, f $ g a = f (g a). Is there a right-associated operator like that in Unison?

There are a few options.
You can use let. For example, f let g a is the same as f (g a). This is because let opens a block, which is a sequence of statements. In this case the only statement in the block is the expression g a which becomes the value the block returns. So you could write e.g.
isSome let head let List.map increment [1,2,3]
There is a function application operator:
(base.Function.<|) : (a ->{e} b) -> a ->{e} b
so you could write f <| g a. However, Unison does not have any operator precedence rules, so all operators associate to the left. So if you want to do nested applications like
isSome <| (head <| List.map increment [1,2,3])
you will need to use parentheses anyway. However, since all operators associate to the left, you can just use the |> operator instead:
(base.Function.|>) : a -> (a ->{e} b) ->{e} b
Then you can write (flipping the order of the functions):
[1,2,3] |> List.map increment |> head |> isSome
You can use function composition:
(base.Function.<<) : (b ->{e} c) -> (a ->{e} b) -> a ->{e} c
This lets you write
isSome << head << List.map increment <| [1,2,3]
Which is equivalent to the Haskell expression:
isJust . listToMaybe . map (+1) $ [1,2,3]

Related

Is there a specific type for mathematical functions in Haskell?

I want to write a function that takes a mathematical function (/,x,+,-), a number to start with and a list of numbers. Then, it's supposed to give back a list.
The first element is the starting number, the second element the value of the starting number plus/minus/times/divided by the first number of the given list. The third element is the result of the previous result plus/minus/times/divided by the second result of the given list, and so on.
I've gotten everything to work if I tell the code which function to use but if I want to let the user input the mathematical function he wants, there are problems with the types. Trying :t (/) for example gives out Fractional a => a -> a -> a, but if you put that at the start of your types, it fails.
Is there a specific type to distinguish these functions (/,x,+,-)? Or is there another way to write this function succesfully?
prefix :: (Fractional a, Num a) => a -> a -> a -> a -> [a] -> [a]
prefix (f) a b = [a] ++ prefix' (f) a b
prefix' :: (Fractional a, Num a) => a -> a -> a -> a -> [a] -> [a]
prefix' (z) x [] = []
prefix' (z) x y = [x z (head y)] ++ prefix' (z) (head (prefix' (z) x y)) (tail y)
A right solution would be something like this:
prefix (-) 0 [1..5]
[0,-1,-3,-6,-10,-15]
Is there a specific type to distinguish these functions (/,*,+,-)?
I don't see a reason to do this. Why is \x y -> x+y considered "better" than \x y -> x + y + 1. Sure adding two numbers is something that most will consider more "pure". But it is strange to restrict yourself to a specific subset of functions. It is also possible that for some function \x y -> f x y - 1 "happens" to be equal to (+), except that the compiler can not determine that.
The type checking will make sure that one can not pass functions that operate on numbers, given the list contains strings, etc. But deliberately restricting this further is not very useful. Why would you prevent programmers to use your function for different purposes?
Or is there another way to write this function succesfully?
What you here describe is the scanl :: (b -> a -> b) -> b -> [a] -> [b] function. If we call scanl with scanl f z [x1, x2, ..., xn], then we obtain a list [z, f z x1, f (f z x1) x2, ...]. scanl can be defined as:
scanl :: (b -> a -> b) -> b -> [a] -> [b]
scanl f = go
where go z [] = [z]
go z (x:xs) = z : go (f z x) xs
We thus first emit the accumulator (that starts with the initial value), and then "update" the accumulator to f z x with z the old accumulator, and x the head of the list, and recurse on the tail of the list.
If you want to restrict to these four operations, just define the type yourself:
data ArithOp = Plus | Minus | Times | Div
as_fun Plus = (+)
as_fun Minus = (-)
as_fun Times = (*)
as_fun Div = (/)

Replacing functions in composite function in haskell

I'm trying to become familiar with Haskell and I was wondering if the following was possible and if so, how?
Say I have a set of functions {f,g,..} for which I was to define a replacement function {f',g',..}. Now say I have a function c which uses these functions (and only these functions) inside itself e.g. c x = g (f x). Is there a way to automatically define c' x = g' (f' x) without explicitly defining it?
EDIT: By a replacement function f' I mean some function that is conceptually relates to f by is altered in some arbitrary way. For example, if f xs ys = (*) <$> xs <*> ys then f' (x:xs) (y:ys) = (x * y):(f' xs ys) etc.
Many thanks,
Ben
If, as seems to be the case with your example, f and f' have the same type etc., then you can easily pass them in as extra parameters. Like
cGen :: ([a] -> [a] -> [a]) -> (([a] -> [a]) -> b) -> [a] -> b
cGen f g x = g (f x)
...which BTW could also be written cGen = (.)...
If you want to group together specific “sets of functions”, you can do that with a “configuration type”
data CConfig a b = CConfig {
f :: [a] -> [a] -> [a]
, g :: ([a] -> [a]) -> b
}
cGen :: CConfig a b -> [a] -> b
cGen (CConfig f g) = f . g
The most concise and reliable way to do something like this would be with RecordWildCards
data Replacer ... = R {f :: ..., g :: ...}
c R{..} x = g (f x)
Your set of functions now is now pulled from the local scope from the record, rather than a global definition, and can be swapped out for a different set of functions at your discretion.
The only way to get closer to what you want would to be to use Template Haskell to parse the source and modify it. Regular Haskell code simply cannot inspect a function in any way - that would violate referential transparency.

Haskell too many arguments error

I am learning Haskell. I am trying to make a function that deletes integers out of a list when met with the parameters of a certain function f.
deleteif :: [Int] -> (Int -> Bool) -> [Int]
deleteif x f = if x == []
then []
else if head x == f
then deleteif((tail x) f)
else [head x] ++ deleteif((tail x) f)
I get the following errors :
function tail is applied to two arguments
'deleteif' is applied to too few arguments
The issue is that you don't use parentheses to call a function in Haskell. So you just need to use
if f (head x)
then deleteif (tail x) f
else [head x] ++ deleteif (tail x) f
the problem is in deleteif((tail x) f)
it becomes deleteif (tail x f)
so tail gets 2 arguments
and then deleteif a
so deleteif gets 1 argument
you want deleteif (tail x) f
head x == f is wrong you want `f (head x)
you can use pattern matching ,guards and make it more generic
deleteif :: [a] -> (a -> Bool) -> [a]
deleteif [] _ = []
deleteif (x:xs) f
| f x = deleteif xs f
| otherwise = x : deleteif xs f
As already said, deleteif((tail x) f) is parsed as deleteif (tail x f), which means tail is applied to the two arguments x and f, and the result would then be passed on as the single argument to deleteif. What you want is deleteif (tail x) f, which is equivalent to (deleteif (tail x)) f and what most languages1 would write deleteif(tail x, f).
This parsing order may seem confusing initially, but it turns out to be really useful in practice. The general name for the technique is Currying.
For one thing, it allows you to write dense statements without needing many parentheses – in fact deleteif (tail x f) could also be written deleteif $ tail x f.
More importantly, because the arguments don't need to be “encased” in a single tuple, you don't need to supply them all at once but automatically get partial application when you apply to only one argument. For instance, you could use this function like that: deleteif (>4) [1,3,7,5,2,9,7] to yield [7,5,9,7]. This works by partially applying the function2 > to 4, leaving a single-argument function which can be used to filter the list.
1Indeed, this style is possible in Haskell as well: just write the signatures of such multi-argument functions as deleteif :: ([Int], Int->Bool) -> [Int]. Or write uncurry deleteif (tail x, f). But it's definitely better you get used to the curried style!
2Actually, > is an infix which behaves a bit different – you can partially apply it to either side, i.e. you can also write deleteif (4>) [1,3,7,5,2,9,7] to get [1,3,2].

Using an element against an entire list in Haskell

I have an assignment and am currently caught in one section of what I'm trying to do. Without going in to specific detail here is the basic layout:
I'm given a data element, f, that holds four different types inside (each with their own purpose):
data F = F Float Int, Int
a function:
func :: F -> F-> Q
Which takes two data elements and (by simple calculations) returns a type that is now an updated version of one of the types in the first f.
I now have an entire list of these elements and need to run the given function using one data element and return the type's value (not the data element). My first analysis was to use a foldl function:
myfunc :: F -> [F] -> Q
myfunc y [] = func y y -- func deals with the same data element calls
myfunc y (x:xs) = foldl func y (x:xs)
however I keep getting the same error:
"Couldn't match expected type 'F' against inferred type 'Q'.
In the first argument of 'foldl', namely 'myfunc'
In the expression: foldl func y (x:xs)
I apologise for such an abstract analysis on my problem but could anyone give me an idea as to what I should do? Should I even use a fold function or is there recursion I'm not thinking about?
The type of foldl is
foldl :: (a -> b -> a) -> a -> [b] -> a
but the type of func is
-- # a -> b -> a
func :: F -> F -> Q
The type variable a cannot be simultaneously F and Q, thus the error.
If the Q can be converted to and from F, you could use
myfunc y xs = foldl (func . fromQ) (toQ y) xs
where
func . fromQ :: Q -> F -> Q
toQ y :: Q
xs :: [F]
so this satisfies all the type requirements, and will return the final Q.
maybe you need map?
map :: (f -> q) -> [f] -> [q]
it evaluates a function on each element in a list and gives a list of the results. I'm not sure why your function takes two Fs though, possibly to work with foldl?

Function application: Why is $ used here?

A while ago, I asked a question about $, and got useful answers -- in fact, I thought I understood how to use it.
It seems I was wrong :(
This example shows up in a tutorial:
instance Monad [] where
xs >>= f = concat . map f $ xs
I can't for the life of me see why $ was used there; ghci isn't helping me either, as even tests I do there seem to show equivalence with the version that would simply omit the $. Can someone clarify this for me?
The $ is used here because it has lower precedence than normal function application.
Another way to write this code is like so:
instance Monad [] where
xs >>= f = (concat . map f) xs
The idea here is to first construct a function (concat . map f) and then apply it to its argument (xs). As shown, this can also be done by simply putting parenthesis around the first part.
Note that omitting the $ in the original definition is not possible, it will result in a type error. This is because the function composition operator (the .) has a lower precedence than normal function application effectively turning the expression into:
instance Monad [] where
xs >>= f = concat . (map f xs)
Which doesn't make sense, because the second argument to the function composition operator isn't a function at all. Although the following definition does make sense:
instance Monad [] where
xs >>= f = concat (map f xs)
Incidentally, this is also the definition I would prefer, because it seems to me to be a lot clearer.
I'd like to explain why IMHO this is not the used style there:
instance Monad [] where
xs >>= f = concat (map f xs)
concat . map f is an example of so-called pointfree-style writing; where pointfree means "without the point of application". Remember that in maths, in the expression y=f(x), we say that f is applied on the point x. In most cases, you can actually do a final step, replacing:
f x = something $ x
with
f = something
like f = concat . map f, and this is actually pointfree style.
Which is clearer is arguable, but the pointfree style gives a different point of view which is also useful, so sometimes is used even when not exactly needed.
EDIT: I have replaced pointless with pointfree and fixed some examples, after the comment by Alasdair, whom I should thank.
The reason $ is used here is doe to the type signature of (.):
(.) :: (b -> c) -> (a -> c) -> a -> c
Here we have
map f :: [a] -> [[b]]
and
concat :: [[b]] -> [b]
So we end up with
concat . map f :: [a] -> [b]
and the type of (.) could be written as
(.) :: ([[b]] -> [b]) -> ([a] -> [[b]]) -> [a] -> [b]
If we were to use concat . map f xs, we'd see that
map f xs :: [[b]]
And so cannot be used with (.). (the type would have to be (.) :: (a -> b) -> a -> b