Say I have a haskell function f n l = filter (n<) l where it takes an integer n and list l and returns all of the integers in l greater then n.
I'm trying to figure out how to best write this function in a language like Joy. I've generally had good luck with converting the haskell function to pointfree form f = filter . (<) and then trying to rewrite it in Joy from there. But I can't figure out how to simulate partial function application in a concatenative language.
So far, I've tried to do something like swap [[>] dip] filter, but it seems like there must be a better/cleaner way to write this.
Also, I'm experimenting with writing my own concatenative language and was wondering if lazy-evaluation could be compatible with concatenative languages.
swap [[>] dip] filter won’t work because it assumes n is accessible for each call to the quotation by which you’re filtering; that implies filter can’t leave any intermediate values on the stack while it’s operating, and > doesn’t consume n. You need to capture the value of n in that quotation.
First “eta”-reduce the list parameter:
l n f = l [ n > ] filter
n f = [ n > ] filter
Then capture n by explicitly quoting it and composing it with >:
n f = n quote [ > ] compose filter
(Assuming quote : a -> (-> a) a.k.a. unit, takes a value and wraps it in a quotation and compose : (A -> B) (B -> C) -> (A -> C) a.k.a. cat, concatenates two quotations.)
Then just “eta”-reduce n:
f = quote [ > ] compose filter
I put “eta” in scare quotes because it’s a little more general than in lambda calculus, working for any number of values on the stack, not just one.
You can of course factor out partial application into its own definition, e.g. the papply combinator in Cat, which is already defined as swons (swap cons) in Joy, but can also be defined like so:
DEFINE
papply (* x [F] -- [x F] *)
== [unit] dip concat ;
f (* xs n -- xs[>=n] *)
== [>] papply filter .
In Kitten this could be written in a few different ways, according to preference:
// Point-free
function \> compose filter
// Local variable and postfix
-> n; { n (>) } filter
// Local variable and operator section
-> n; \(n <) filter
Any evaluation strategy compatible with functional programming is also compatible with concatenative programming—popr is a lazy concatenative language.
Related
So I'm looking for a way to force some operators which are defined as right-associative to be applied in left associative manner. I've seen that Haskell has $ operator, which changes precedence but sadly not the associativity of the function application.
To be exact, I specifically look for the way to make a long concatenation chain to evaluate arguments in left associative manner.
Does Haskell has something like this?
Actually, $ does change the associativity of function application.
Normal function application associates to the left (and this behavior cannot be changed), so the expression f x y associates as:
f x y = (f x) y
On the other hand, $ associates to the right (and this behavior is part of the library definition of $ and could be changed by redefining your own version of $ or some other operator), so:
f $ x $ y = f $ (x $ y) = f (x y)
with the first equality following from the associativity of $ and the last equality following from its definition.
It's possible that what you're really talking about is not the associativity but rather the order in which the argument and function are combined. Normal function application is func arg, but if you want arg func, you can do it with an operator. The (&) operator in Data.Function does this. It's a reversed version of $, which means that it associates to the left:
y & f & g = (y & f) & g
but it ALSO has a different definition, so y & f applies the function f to the argument y, instead of applying y to f.
So, you can, as in #Iceland_jack's example, write:
"Hello world" & -- start with a string
words & -- break it into words
map length & -- get the length of each word
sum -- sum the lengths
If this is what you mean by "a long concatenation chain to evaluate arguments in left associative manner", then you've got your answer. Note that the definition of & isn't too complicated. It looks like this. The infixl statement sets both the precedence and the (left) associativity of the operator:
infixl 1 &
(&) :: a -> (a -> b) -> b
x & f = f x
If you are instead talking about an operator that applies a single function to multiple arguments but is written with the arguments first (in reverse order), like:
"string" ?? 2 ?? take = take 2 "string"
for some operator ??, then I don't think there's any built-in operator like that, but you can do it yourself by defining an operator that is right associative like $ but has the same core definition as &:
infixr 0 ??
(??) :: a -> (a -> b) -> b
x ?? f = f x
I was introduced to the use of fold in defining function. I have an idea how that works but im not sure why one should do it. To me, it feels like just simplifying name of data type and data value ... Would be great if you can show me examples where it is significant to use fold.
data List a = Empty | (:-:) a (List a)
--Define elements
List a :: *
[] :: List a
(:) :: a -> List a -> List a
foldrList :: (a -> b -> b) -> b -> List a -> b
foldrList f e Empty = e
foldrList f e (x:-:xs) = f x (foldrList f e xs)
The idea of folding is a powerful one. The fold functions (foldr and foldl in the Haskell base library) come from a family of functions called Higher-Order Functions (for those who don't know - these are functions which take functions as parameters or return functions as their output).
This allows for greater code clarity as the intention of the program is more clearly expressed. A function written using fold functions strongly indicates that there is an intention to iterate over the list and apply a function repeatedly to obtain an output. Using the standard recursive method is fine for simple programs but when complexity increases it can become difficult to understand quickly what is happening.
Greater code re-use can be achieved with folding due to the nature of passing in a function as the parameter. If a program has some behaviour that is affected by the passing of a Boolean or enumeration value then this behaviour can be abstracted away into a separate function. The separate function can then be used as an argument to fold. This achieves greater flexibility and simplicity (as there are 2 simpler functions versus 1 more complex function).
Higher-Order Functions are also essential for Monads.
Credit to the comments for this question as well for being varied and informative.
Higher-order functions like foldr, foldl, map, zipWith, &c. capture common patterns of recursion so you can avoid writing manually recursive definitions. This makes your code higher-level and more readable: instead of having to step through the code and infer what a recursive function is doing, the programmer can reason about compositions of higher-level components.
For a somewhat extreme example, consider a manually recursive calculation of standard deviation:
standardDeviation numbers = step1 numbers
where
-- Calculate length and sum to obtain mean
step1 = loop 0 0
where
loop count sum (x : xs) = loop (count + 1) (sum + x) xs
loop count sum [] = step2 sum count numbers
-- Calculate squared differences with mean
step2 sum count = loop []
where
loop diffs (x : xs) = loop ((x - (sum / count)) ^ 2 : diffs) xs
loop diffs [] = step3 count diffs
-- Calculate final total and return square root
step3 count = loop 0
where
loop total (x : xs) = loop (total + x) xs
loop total [] = sqrt (total / count)
(To be fair, I went a little overboard by also inlining the summation, but this is roughly how it may typically be done in an imperative language—manually looping.)
Now consider a version using a composition of calls to standard functions, some of which are higher-order:
standardDeviation numbers -- The standard deviation
= sqrt -- is the square root
. mean -- of the mean
. map (^ 2) -- of the squares
. map (subtract -- of the differences
(mean numbers)) -- with the mean
$ numbers -- of the input numbers
where -- where
mean xs -- the mean
= sum xs -- is the sum
/ fromIntegral (length xs) -- over the length.
This more declarative code is also, I hope, much more readable—and without the heavy commenting, could be written neatly in two lines. It’s also much more obviously correct than the low-level recursive version.
Furthermore, sum, map, and length can all be implemented in terms of folds, as well as many other standard functions like product, and, or, concat, and so on. Folding is an extremely common operation on not only lists, but all kinds of containers (see the Foldable typeclass), because it captures the pattern of computing something incrementally from all elements of a container.
A final reason to use folds instead of manual recursion is performance: thanks to laziness and optimisations that GHC knows how to perform when you use fold-based functions, the compiler may fuse a series of folds (maps, &c.) together into a single loop at runtime.
Doing the third of the 99-Haskell problems (I am currently trying to learn the language) I tried to incorporate pattern matching as well as recursion into my function which now looks like this:
myElementAt :: [a] -> Int -> a
myElementAt (x ++ xs) i =
if length (x ++ xs) == i && length xs == 1 then xs!!0
else myElementAt x i
Which gives me Parse error in pattern: x ++ xs. The questions:
Why does this give me a parse error? Is it because Haskell is no idea where to cut my list (Which is my best guess)?
How could I reframe my function so that it works? The algorithmic idea is to check wether the list has the length as the specified inde; if yes return the last elemen; if not cut away one element at the end of the list and then do the recursion.
Note: I know that this is a really bad algorithm, but it I've set myself the challenge to write that function including recursion and pattern matching. I also tried not to use the !! operator, but that is fine for me since the only thing it really does (or should do if it compiled) is to convert a one-element list into that element.
Haskell has two different kinds of value-level entities: variables (this also includes functions, infix operators like ++ etc.) and constructors. Both can be used in expressions, but only constructors can also be used in patterns.
In either case, it's easy to tell whether you're dealing with a variable or constructor: a constructor always starts with an uppercase letter (e.g. Nothing, True or StateT) or, if it's an infix, with a colon (:, :+). Everything else is a variable. Fundamentally, the difference is that a constructor is always a unique, immediately matcheable value from a predefined collection (namely, the alternatives of a data definition), whereas a variable can just have any value, and often it's in principle not possible to uniquely distinguish different variables, in particular if they have a function type.
Yours is actually a good example for this: for the pattern match x ++ xs to make sense, there would have to be one unique way in which the input list could be written in the form x ++ xs. Well, but for, say [0,1,2,3], there are multiple different ways in which this can be done:
[] ++[0,1,2,3]
[0] ++ [1,2,3]
[0,1] ++ [2,3]
[0,1,2] ++ [3]
[0,1,2,3]++ []
Which one should the runtime choose?
Presumably, you're trying to match the head and tail part of a list. Let's step through it:
myElementAt (x:_) 0 = x
This means that if the head is x, the tail is something, and the index is 0, return the head. Note that your x ++ x is a concatenation of two lists, not the head and tail parts.
Then you can have
myElementAt(_:tl) i = myElementAt tl (i - 1)
which means that if the previous pattern was not matched, ignore the head, and take the i - 1 element of the tail.
In patterns, you can only use constructors like : and []. The append operator (++) is a non-constructor function.
So, try something like:
myElementAt :: [a] -> Int -> a
myElementAt (x:xs) i = ...
There are more issues in your code, but at least this fixes your first problem.
in standard Haskell pattern matches like this :
f :: Int -> Int
f (g n 1) = n
g :: Int -> Int -> Int
g a b = a+b
Are illegal because function calls aren't allowed in patterns, your case is just a special case as the operator ++ is just a function.
To pattern match on lists you can do it like this:
myElementAt :: [a] -> Int -> a
myElementAt (x:xs) i = // result
But in this case x is of type a not [a] , it is the head of the list and xs is its tail, you'll need to change your function implementation to accommodate this fact, also this function will fail with the empty list []. However that's the idiomatic haskell way to pattern match aginst lists.
I should mention that when I said "illegal" I meant in standard Haskell, there are GHC extensions that give something similar to that , it's called ViewPatterns But I don't think you need it especially that you're still learning.
I'm getting used to Haskell's higher-order functions. Usually I can replace explicit patterns of recursion with functions like map, fold, and scan. However, I often run into the following recursion pattern which I don't understand how to express using higher-order functions:
f (x:[]) = k x
f (x:xs) = g x (f xs)
For instance, suppose I am representing analytic tableaux. Then I create a data type such as:
data Tableau = N Expr | S Expr (Tableau) | B Expr (Tableau) (Tableau)
If I want to convert a list of Exprs into a tableau structure, I want a function part of which might resemble:
f (x:[]) = N x
f (x:xs) = S x (f xs)
Now, I see three options: (1) create a function which decides, given a tableau and a list, whether the next branch in the tableau should be an S or N (or B, but we'll ignore that case); (2) use a higher-order function to encapsulate the recursion pattern of f; (3) use a function like f.
What would the best option be?
I'd most probably use the following:
f xs = foldr g (k (last xs)) (init xs)
It basically means that the end of the list is replaced by k x when folding. Thanks to lazy evaluation present everywhere, it works even for infinite lists.
There are two other solutions - adding empty case and using Maybe.
A) adding empty case:
It would be best if f [] was well-defined. Then, you could write the definition as
f [] = c
f (x:xs) = g x (f xs)
which is f = foldr g c. For example, if you change
data Tableau = N Expr | S Expr Tableau | B Expr Tableau Tableau
to
data Tableau = N | S Expr Tableau | B Expr Tableau Tableau
then you can represent single-element tableaux as S expr N, and the function is defined as one-liner
f = foldr S N
It's the best solution as long the empty case makes sense.
B) use Maybe:
On the other hand, if f [] cannot be sensibly defined, it's worse.
Partial functions are often considered ugly. To make it total, you can use Maybe. Define
f [] = Nothing
f [x] = Just (k x)
f (x:xs) = Just (g x w)
where Just w = f xs
It is a total function - that's better.
But now you can rewrite the function into:
f [] = Nothing
f (x:xs) = case f xs of
Nothing -> Just (k x)
Just w -> Just (g x w)
which is a right fold:
addElement :: Expr -> Maybe Tableaux -> Maybe Tableaux
addElement x Nothing = Just (N x)
addElement x (Just w) = Just (S x w)
f = foldr addElement Nothing
In general, folding is idiomatic and should be used when you fit the recursion pattern. Otherwise use explicit recursion or try to reuse existing combinators. If there's a new pattern, make a combinator, but only if you'll use the pattern a lot - otherwise it's overkill. In this case, the pattern is fold for nonempty lists defined by: data List a = End a | Cons a (List a).
If I've understood the question properly, then here's my evaluation of your options:
It's probably a bit nasty to have to match the (presumably arbitrarily complex?) tableau out from underneath the constructor in order to write that function. This approach seems somewhat brittle, although it would probably work just fine.
I don't see the need to generalise the pattern out, given that it's a recursive function operating on a recursive structure. Introducing a higher-order pattern would (I think) obfuscate the actual logic behind performing a recursive traversal of this data structure.
I think this makes a good deal of sense. As you've observed, it's a reasonably recognised "pattern", but I think it matches the description of the algorithm well to write it down in exactly this way. It may not be as generalisable or reusable, but given that it's essentially the crux of the algorithmic approach, I think it makes sense to write the cases directly as you have done in a function like f. This would be my favoured approach.
Sorry to not provide a particularly concrete answer, but it is a reasonably subjective answer, so given the three options above, I would pick option 3 for reasons of clarity and readability.
I am reading a tutorial that uses the following example (that I'll generalize somewhat):
f :: Foo -> (Int, Foo)
...
fList :: Foo -> [Int]
fList foo = x : fList bar
where
(x, bar) = f foo
My question lies in the fact that it seems you can refer to x and bar, by name, outside of the tuple where they are obtained. This would seem to act like destructuring parameter lists in other languages, if my guess is correct. (In other words, I didn't have to do the following:)
fList foo = (fst tuple) : fList (snd tuple)
where
tuple = f foo
Am I right about this behavior? I've never seen it mentioned yet in the tutorials/books I've been reading. Can someone point me to more info on the subject?
Edit: Can anything (lists, arrays, etc.) be destructured in a similar way, or can you only do this with tuples?
Seeing your edit, I think what your asking about is Pattern matching.
And to answer your question: Yes, anything you can construct, you can also 'deconstruct' using the constructors. For example, you're probably familiar with this form of pattern matching:
head :: [a] -> a
head (x:xs) = x
head [] = error "Can't take head of empty list"
However, there are more places where you can use pattern matching, other valid notations are:
head xs = case xs of
(y:ys) -> y
[] -> error "Can't take head of empty list"
head xs = let (y:ys) = xs
in y
head xs = y
where
(y:ys) = xs
Note that the last two examples are a bit different from the first to because they give different error messages when you call them with an empty list.
Although these examples are specific to lists, you can do the same with other data types, like so:
first :: (a, b) -> a
first tuple = x
where
(x, y) = tuple
second :: (a, b) -> b
second tuple = let (x, y) = tuple
in y
fromJust :: Maybe a -> a
fromJust ma = x
where
(Just x) = ma
Again, the last function will also crash if you call it with Nothing.
To sum up; if you can create something using constructors (like (:) and [] for lists, or (,) for tuples, or Nothing and Just for Maybe), you can use those same constructors to do pattern matching in a variety of ways.
Am I right about this behavior?
Yes. The names exist only in the block where you have defined them, though. In your case, this means the logical unit that your where clause is applied to, i.e. the expression inside fList.
Another way to look at it is that code like this
x where x = 3
is roughly equivalent to
let x = 3 in x
Yes, you're right. Names bound in a where clause are visible to the full declaration preceding the where clause. In your case those names are f and bar.
(One of the hard things about learning Haskell is that it is not just permitted but common to use variables in the source code in locations that precede the locations where those variables are defined.)
The place to read more about where clauses is in the Haskell 98 Report or in one of the many fine tutorials to be found at haskell.org.