Haskell, combining Do and if - haskell

Hi I was wondering whether there was a way to use do if in haskell in this kind of way
doIfFunction :: Eq a => [a]->[a] ->[a]
doIfFunction l1 l2 = do
if l /= something then (l2++something) else l2
if l /= something2 then (l2++something2) else l2
l2
Basically if this something function returns a different value I want it to add it to l2 then return l2. I keep getting l2 as being empty at the end and it shouldn't be, is this because of the else l2 does it reset the value of l2 to what it was at the start?
If so could I do something like this?
doIfFunction :: Eq a => [a]->[a] ->[a]
doIfFunction l1 l2 = do
if l /= something then (let l2 = l2++something) else l2
if l /= something2 then (let l2 = l2++something2) else l2
l2
This gives errors, but I was wondering if this is on the right lines.
When the doIfFunction is being called it will always be doIfFunction l [] where l contains values and [] is empty

Generally, you should avoid to think about modifying anything in Haskell. In fact, you can't, the language doesn't allow it. At all†!
Instead of modifying the list l2 itself, you think about creating additional lists which are modified versions of l2. (The immediate benefit is that you can still use the original l2 anywhere else; in particular it's fine if some other function / thread still needs this old version and you weren't aware of it.)
I.e., instead of
do
modify_something_about_l2
modify_something_else_about_l2
yield_some_result
you want to just evaluate the result of a function-application chain, like
f l2 = some_other_modification (some_modification (l2))
or, as we prefer to write it,
f = some_other_modification . some_modification
In your particular case:
doIfFunction l1
= (\l2 -> if l /= something2 then (l2++something2) else l2)
. (\l2 -> if l /= something then (l2++something) else l2)
If you don't like the “backwards style“ you can also replace the composition operator . with its flipped version:
import Control.Arrow
doIfFunction l1
= (\l2 -> if l /= something then (l2++something) else l2)
>>> (\l2 -> if l /= something2 then (l2++something2) else l2)
Also, you can, via eta-reduction, avoid mentioning the intermediate lists at all:
doIfFunction l1
= (if l /= something then (++something) else id)
>>> (if l /= something2 then (++something2) else id)
That said...
You're probably thinking: it's mighty inefficient to always create new modified versions of everything, instead of just modifying in-place. Well, sometimes it is, often it is actually no problem at all.
You example is in fact one where it is a problem: to append something to l2, a copy of the entire list needs to be made. Maybe you can avoid this problem very easily: if instead of appending, you prepend:
doIfFunction l1
= (if l /= something then (something++) else id)
>>> (if l /= something2 then (something2++) else id)
then there's no performance penalty. The reason being: a list is just a chain of elements (heads), each with references to the rest of the list. Pre-pending an element is just a matter of making a new head and linking it to the already existing list!
†Even with clever lazy prepending, sometimes the pure-functional style is significantly more time-expensive. Don't worry: although Haskell does not allow modifying values, there are types which encapsulate the concept of destructive modifications, namely the ST monad. So you can still implement algorithms that need destructive updates efficiently, but basically you don't do it in Haskell but in an embedded “domain-specific imperative language”, that integrates seamlessly with Haskell.

Just put the if clause in the let statement:
doIfFunction :: Eq a => [a] -> [a] -> [a]
doIfFunction l1 l2 = do
let l2' = if l /= something then l2 ++ something else l2
let l2'' = if l /= something2 then l2' ++ something2 else l2'
l2''
But in this case you don't really need the do notation since you don't use any monadic operation. I believe you want to use the do notation to simulate imperative-style programming. Consider using a where if you think it's more readable:
doIfFunction :: Eq a => [a] -> [a] -> [a]
doIfFunction l1 l2 = result
where newL2 = if l /= something then l2 ++ something else l2
result = if l /= something2 then newL2 ++ something2 else newL2
Alternatively, when you will be more familiar with Haskell, you could use leftaroundabout's answer (that would be the most idiomatic way to write what you want to do).

Related

Palindrome and Danvy's remark on direct style

Here is some code deciding whether a list is a palindrome in n+1 comparisons, in "direct style"
pal_d1 :: Eq a => [a] -> Bool
pal_d1 l = let (r,_) = walk l l in r
where walk l [] = (True,l)
walk l (_:[]) = (True,tail l)
walk (x:l) (_:_:xs) = let (r, y:ys) = walk l xs
in (r && x == y, ys)
which can be tested on a few example
-- >>> pal_d1 [1,2,1]
-- True
-- >>> pal_d1 [1,2,2,1]
-- True
-- >>> pal_d1 [1,2,3,4,2,1]
-- False
Danvy claims in "There and back again" there is no direct style solution without a control operator (right before 4.2) due to the non linear use of the continuation in CPS style solution below :
pal_cps1 :: Eq a => [a] -> Bool
pal_cps1 l = walk l l (\_ -> trace "called" True)
where
walk l [] k = k l
walk l (_:[]) k = k (tail l)
walk (x:xs) (_:_:ys) k = walk xs ys (\(r:rs) -> x == r && k rs)
How is the first code not contradicting this assertion ?
(and how is the continuation not used linearly ?)
He does not claim that there is no solution without a control operator.
The continuation is not used linearly and therefore mapping this program back to direct style requires a control operator.
The context of the paper is to study systematic transformations between direct style and CPS, and the claim of that paragraph is that going back from CPS is tricky if the continuation is used in fancy ways.
With some effort you can wrangle it back into a nice shape, but the question remains, how might a compiler do that automatically?
(and how is the continuation not used linearly ?)
In the paper, the continuation is on the right of andalso (&&) so it's discarded if the left operand is False.
In operational semantics, you can view the continuation as an evaluation context, and in that view discarding the continuation corresponds to throwing an exception. One can certainly do it, but the point is that this requires extra machinery in the source language.
The CPS code (in the question's original version --- since edited by OP) seems faulty. Looks like it should be
walk (x:xs) (_:_:ys) k = walk xs ys (\(z:zs) -> x == z && k zs)
The non-CPS code starts the comparisons from the middle, and does n `div` 2 comparisons, for a list of length n. It continues testing even if a mismatch is discovered, so, is "linear".
The CPS code exits right away in such a case because (False && undefined) == False holds; so is "non-linear". The two are not equivalent so the first doesn't say anything about the second.
As the other answer is saying, not calling the continuation amounts to throwing an exception in a code without continuations, what the paper's author apparently calls "the direct [i.e., non-CPS(?) --wn] style".
(I haven't read the paper).
It isn't difficult at all to code the early-exiting solution in the "direct" style, by the way. We would just use the same turtle-and-hare trick to discover the halves while also building the first half in reverse, and then call and $ zipWith (==) first_half_reversed second_half in Haskell, or its equivalent short-circuiting direct recursive variant, in a strict language like e.g. Scheme.

Haskell: Obtaining the Nth element in a Snoc list

I wrote the following function to find the Nth element on a given Snoc list (reverse cons) but I think it's not the most optimal solution to the problem. I was wondering if you would please share some insights, code or advice to see a different solution; one that you might consider does the job more efficiently:
Here's my function:
data ListS a = NilS
|Snoc (ListS a) a deriving Show
len :: ListS a -> Int
len NilS = 0
len (Snoc a b) = 1 + len(a)
nthElementS :: Int -> ListS a -> a
nthElementS _ NilS = error "Empty List"
nthElementS n s = if n < 0 || n >= len(s) then error "Invalid Index"
else nthAux ((len(s)-1)-n) s where
nthAux 0 (Snoc a b) = b
nthAux m (Snoc a b) = nthAux (m-1) a
Some examples:
Main> nthElementS 0 (Snoc (Snoc (Snoc (Snoc (Snoc NilS 1) 2) 3) 4) 5)
1
Main> nthElementS 2 (Snoc (Snoc (Snoc (Snoc (Snoc NilS 1) 2) 3) 4) 5)
3
As an additional inquiry: What would be the best way to implement a function that concatenates 2 Snoc lists? I am already thinking of a solution but it would require an auxiliary function to keep track of the Nth position, and again, I feel that's not going to make full use of Haskell's advantages over other languages.
Thanks in advance.
We can use a "try-and-error" approach where we first try to find that element in the "prefix list", and if that is not sufficient (since the index is larger), we then try the current element. If that still is not enough, it is up to the "parent call" to handle the situation. We can do this by first defining a function with a slightly different output type:
nthShelp :: Int -> ListS a -> Either a Int
So it returns Left x in case it has found the element (x being the element), or Rightn, withn` the "remaining" elements it needs to walk through.
So we can define this with:
nthShelp :: Int -> ListS a -> Either a Int
nthShelp n NilS = Right n
nthShelp n (Snoc hs t) = progress nhs
where nhs = nthElementS n hs
progress lx#(Left _) = lx
progress (Right 0) = Left t
progress (Right n) = Right (n-1)
So we first call recursively on the head of the list, and then the recursive calls are resolved by decrementing the index until it hits zero, in which case we return the corresponding Left t, and that Left t is than passed back out of the recursive calls.
We can make use of the fact that Either a is a Monad istance, and write this more effective like:
nthShelp :: Int -> ListS a -> Either a Int
nthShelp n NilS = Right n
nthShelp n (Snoc hs t) = nthElementS n hs >>= progress
where progress 0 = Left t
progress n = Right (n-1)
Then we can write nthElementS in terms of nthShelp with:
nthElementS :: Int -> ListS a -> a
nthElementS n l | n < 0 = error "Index too small"
| Left a <- nthShelp n l = a
| otherwise = error "Index too large"
In terms of time complexity, it is still O(n) (with n the length of the list, not the index we want to obtain). There is no way to do it better with this data structure, since we need to know the number of elements in the prefix, before we know what element to return.
As an additional inquiry: What would be the best way to implement a function that concatenates 2 Cons lists? I am already thinking of a solution but it would require an auxiliary function to keep track of the Nth position, and again, I feel that's not going to make full use of Haskell's advantages over other languages.
Well you can see a concatenation here as replacing the (usally deeply) nested NlS of the second list, by the first list. So if we concatenate concatS l1 NilS, then it is l1, if we concatenate concatS l1 (Snoc NilS x), then it is Snic l1 x). So we can define this recursively as:
concatS :: ListS a -> ListS a -> ListS a
concatS l1 NilS = l1
concatS l1 (Snoc l2 x) = Snoc (concatS l1 l2) x
A disadvantage of the above approach is that it still will work in O(n) if the first list is NilS (so empty). We can add a guard for this, to handle that case:
concatS :: ListS a -> ListS a -> ListS a
concatS NilS = id
concatS l1 = go
where go NilS = l1
go (Snoc l2 x) = Snoc (go l2) x

Haskell where statement returns parse error on input ‘=’

This function I made returns a parse error on input ‘=’
checkappend :: Maybe [a] -> Maybe [a] -> (a -> Bool) -> Maybe [a]
checkappend ml1 ml2 test =
if all test l1
then (Just (l1 ++ l2))
else Nothing
where l1 = fromJust(ml1)
l2 = fromJust(ml2)
The where needs to be indented less than the function body, any consistently:
checkappend ml1 ml2 test =
if all test l1
then Just (l1 ++ l2)
else Nothing
where l1 = fromJust ml1
l2 = fromJust ml2
BTW, using partial functions like head or fromJust is bad style. Better use pattern matching on Maybe arguments! Also, if then else is somewhat unpopular in Haskell – guards tend to look nicer:
checkappend (Just l1) (Just l2) test
| all test l1 = Just $ l1 ++ l2
| otherwise = Nothing
Of course, the pattern match is still incomplete... what to do if one of the arguments is Nothing? I reckon you want to result to be Nothing then, too; that's possible with a catch-all pattern:
checkappend (Just l1) (Just l2) test
| all test l1 = Just $ l1 ++ l2
checkappend _ _ _ = Nothing
Note that this already includes the | otherwise guard: if no guard for a given pattern clause matches, Haskell just continues with the next clause.
A really slick way to write it:
import Control.Monad (guard)
checkAppend m1 m2 test =
do
l1 <- m1
l2 <- m2
guard $ all test l1
return $ l1 ++ l2
This uses the fact that Maybe is a monad with a notion of failure. If either of the arguments is nothing, it fails to extract l1 or l2 and gives Nothing. If the guard argument is false, it gives Nothing. Finally, if all goes well, it gives Just (l1 ++ l2).
For fun, try writing the function I just gave and applying it to two lists of lists, instead of two maybe lists. What does it do? Can you figure out why?

Is there an indexed list in Haskell and is it good or bad?

I am a new comer to the Haskell world and I am wondering if there is something like this:
data IndexedList a = IList Int [a]
findIndex::(Int->Int)->IndexedList a->(a,IndexedList a)
findIndex f (IList x l) = (l!!(f x), IList (f x) l)
next::IndexedList a->(a,IndexedList a)
next x = findIndex (+1) x
I've noticed that this kind of list is not purely functional but kind of useful for some applications. Should it be considered harmful?
Thanks,
Bob
It's certainly useful to have a list that comes equipped with a pointed to a particular location in the list. However, the way it's usually done in Haskell is somewhat different - rather than using an explicit pointer, we tend to use a zipper.
The list zipper looks like this
data ListZipper a = LZ [a] a [a] deriving (Show)
You should think of the middle field a as being the element that is currently pointed to, the first field [a] as being the elements before the current position, and the final field [a] as being the elements after the current position.
Usually we store the elements before the current one in reverse order, for efficiency, so that the list [0, 1, 2, *3*, 4, 5, 6] with a pointer to the middle element, would be stored as
LZ [2,1,0] 3 [4,5,6]
You can define functions that move the pointer to the left or right
left (LZ (a:as) b bs) = LZ as a (b:bs)
right (LZ as a (b:bs)) = LZ (a:as) b bs
If you want to move to the left or right n times, then you can do that with the help of a function that takes another function, and applies it n times to its argument
times n f = (!!n) . iterate f
so that to move left three times, you could use
>> let lz = LZ [2,1,0] 3 [4,5,6]
>> (3 `times` left) lz
LZ [] 0 [1,2,3,4,5,6]
Your two functions findIndex and next can be written as
next :: ListZipper a -> (a, ListZipper a)
next = findIndex 1
findIndex :: Int -> ListZipper a -> (a, ListZipper a)
findIndex n x = let y#(LZ _ a _) = (n `times` right) x in (a, y)
Contrary to what you think this list is in fact purely functional. The reason is that IList (f x) l creates a new list (and does not, as you may think, modify the current IndexedList). It is in general not that easy to create non-purely functional data structures or functions in Haskell, as long as you stay away from unsafePerformIO.
The reason I would recommend against using the IndexedList is that there is no assurance that the index is less than the length of the list. In this case the lookup l!!(f x) will fail with an exception, which is generally considered bad style in Haskell. An alternative could be to use a safe lookup, which returns a Maybe a like the following:
findIndex :: (Int -> Int) -> IndexedList a -> (Maybe a, IndexedList a)
findIndex f (IList i l) = (maybe_x, IList new_i l)
where
new_i = f i
maybe_x = if new_i < length l
then Just (l !! newI)
else Nothing
I can also not think of a usecase where such a list would be useful, but I guess I am limited by my creativity ;)

iterating through a list in haskell

I have a list of list of characters ::[[Char]].
I need to iterate both over the list of strings and also over each character in each string.
Say, my list is present in this variable.
let xs
Please suggest an easy way to iterate.
If you want to apply a function f to every element of a list like this:
[a, b, c, d] → [f a, f b, f c, f d]
then map f xs does the trick. map turns a function on elements to a function on lists. So, we can nest it to operate on lists of lists: if f transforms as into bs, map (map f) transforms [[a]]s into [[b]]s.
If you instead want to perform some IO action for every element of a list (which is more like traditional iteration), then you're probably looking for forM_:1
forM_ :: [a] -> (a -> IO b) -> IO ()
You give it a function, and it calls it with each element of the list in order. For instance, forM_ xs putStrLn is an IO action that will print out every string in xs on its own line. Here's an example of a more involved use of forM_:
main = do
...
forM_ xs $ \s -> do
putStrLn "Here's a string:"
forM_ s print
putStrLn "Now it's done."
If xs contains ["hello", "world"], then this will print out:
Here's a string:
'h'
'e'
'l'
'l'
'o'
Now it's done.
Here's a string:
'w'
'o'
'r'
'l'
'd'
Now it's done.
1 forM_ actually has a more general type, but the simpler version I've shown is more relevant here.
Just that:
[c | x <- xs, c <- x]
The "correct" way to iterate is actually fold. Anything you might ever want to do with a list can be done with a fold. Let's consider what you want to do. You're probably thinking of something like this:
for (row in xs):
for (c in row):
doSomething
The problem is, you're probably making use of mutable variables in doSomething. That's ok, we can deal with that. So suppose you have this.
def iter2d(xs):
outerVar = outerInit
for (row in xs):
innerVar = innerInit(row)
outerVar.adjust1(row)
for (c in row):
innerVar.adjust2(c)
outerVar.adjust3(c, innerVar)
return outerVar
Let's translate that to folds. And immutability.
iter2d :: [[Char]] -> Something
iter2d xs = foldl' outerStep outerInit xs
where outerInit = ... -- same as outerInit above
outerStep acc row = fst $ foldl' innerStep innerInit' row)
where innerInit' = ((adjust1 acc row), innerInit row)
innerInit row = ... -- same as innerInit above
innerStep (outAcc, inAcc) c = (outAcc', inAcc')
where inAcc' = adjust2 inAcc c
outAcc' = adjust3 outAcc c inAcc'
Notice with immutability, we are forced to indicate that outAc' depends on inAcc', rather than inAcc, meaning, the "state" of innerVar after it is updated.
Now you might say "wow that Haskell looks way ugly, why would I ever want to use Haskell". Yes, it does look ugly, but only because I tailored it to be a direct translation of imperative code. Once you get used to using folds instead of "iterating through a list", then you will find that folding is a very powerful technique that lets you do a lot of things in a more elegant way than for loops allow.
map (map f) l
where f :: Char -> Foo is a function to apply to each Char and l :: [[Char]]
returns l' :: [[Foo]]

Resources