I tried to practice haskell a bit but I didn't get the following code to work:
rems :: Int -> [Int] -> [Int]
rems _ [] = []
rems k (x:xs)
| k == x = rems k xs
| otherwise [x] ++ rems k xs
main = print $
rems 3 [5, 3, 2]
This function removes every k from a list x if you call it rems k x. I know that it should be working because we wrote it down in university.
I'm using this IDE: https://repl.it/languages/haskell
It might be useful to know that otherwise isn't a keyword or special symbol like =, it's actually simply a boolean value defined in the prelude as True. I.e., a guard with otherwise works syntactically the same as any other guard, just the condition is trivial. You might also write it
rems _ [] = []
rems k (x:xs)
| k == x = rems k xs
| True = [x] ++ rems k xs
The alignment I chose above (all = aligned and at least two† spaces away from the guard-condition) is completely a matter of taste, but I think it helps avoiding confusion like the one you've found yourself in.
BTW, [x] ++ ... can be shortened to x : .... The preferred form of writing the function is
rems _ [] = []
rems k (x:xs)
| k==x = rems k xs
| otherwise = x : rems k xs
†Most people align the =s but use only one space. That's ok, but IMO k == x = res looks deceptive with all those equals-characters, and k and x further away from each other than from the result. k==x = res seems tidier.
Related
With dependent types, you can either capture function properties in the type signature, like in concatenation with length-indexed lists
(++) : Vect m a -> Vect n a -> Vect (m + n) a
or you can not use dependent types in your signature, like concatenation with standard lists
(++) : List a -> List a -> List a
and write proofs about (++)
appendAddsLength : (xs, ys : List a) -> length (xs ++ ys) = length xs + length ys
lengthNil : length [] = 0
lengthCons : (x : a) -> (xs : List a) -> length (x :: xs) = length xs + 1
Is there any difference between these approaches beyond ergonomics?
The most obvious difference is that, with (++) on Vects, the length is statically known: you can operate on it at compile time. Moreover, you don't need to write any additional proofs in order to ensure that (++) has the expected behavior on Vects, whereas you need to do it for Lists.
That is, (++) on Vect is correct by construction. The compiler will always enforce the desired properties, whether you like it or not, and without the user taking any additional action.
It's important to note that length xs is not really interchangeable with the statically-known size in general. On these data types, length is a function which actually re-computes the length of a List or Vect by walking through it and incrementing a counter:
libs/prelude/Prelude/Types.idr:L403-L407
namespace List
||| Returns the length of the list.
public export
length : List a -> Nat
length [] = Z
length (x :: xs) = S (length xs)
libs/base/Data/Vect.idr:25-28
public export
length : (xs : Vect len elem) -> Nat
length [] = 0
length (_::xs) = 1 + length xs
Even with Vect, the length built into to the type by construction, but the result of applying the length function to a List or Vect is not fundamental at all. In fact, Data.Vect contains a proof that Data.Vect.length that applying length to a Vect n t always returns n:
libs/base/Data/Vect.idr:30-34
||| Show that the length function on vectors in fact calculates the length
export
lengthCorrect : (xs : Vect len elem) -> length xs = len
lengthCorrect [] = Refl
lengthCorrect (_ :: xs) = rewrite lengthCorrect xs in Refl
Using the above proof, we can assert statically, without actually executing length, that the result of length is propositionally equal to the statically-known length of the Vect. But this assurance is not available for List. And it's much more cumbersome to work with in general, likely requiring the use of with ... proof and rewrite a lot more than just using the correct-by-construction type.
I have written a program that takes a message as a string and returns an anagram by padding the message with X's as needed such that the string length has exactly 4 factors then essentially rearranges the message as if it had been organized in a grid and read down instead of across. For example, inputting, "Haskell" would return the string, "HealslkX". I have written a program that encodes this anagram, but am having trouble writing a program that can reverse the previous program and decode the anagram, particularly with the removeX function that should remove the X padding. Here is what I have:
encode:
import Data.List
factors :: Int -> [Int]
factors n = [x | x <- [1..n], n `mod` x == 0]
split :: Int -> [a] -> [[a]]
split _ [] = []
split n xs =
let (ys, zs) = splitAt n xs
in ys : split n zs
encode :: [Char] -> [Char]
encode (x:xs) = if (length (factors (length xs))) == 4 then concat
(transpose (split ((factors (length xs))!!2) xs))
else encode (xs ++ ['X'])
decode:
import Data.List
factors :: Int -> [Int]
factors n = [x | x <- [1..n], n `mod` x == 0]
split :: Int -> [a] -> [[a]]
split _ [] = []
split n xs =
let (ys, zs) = splitAt n xs
in ys : split n zs
removeX :: [a] -> [a]
removeX xs = if (last xs) == 'X' then ((init xs) && removeX xs)
else xs
decode :: [Char] -> [Char]
decode (x:xs) = removeX (concat (transpose (split ((factors (length xs))!!1) xs)))
Just use removeX (init xs) instead of init xs && removeX xs. Haskell is not procedural (you don't write down a sequence of changes to make) but functional (you write down functions that produce new results from old). Haven't read the rest of the code to see if there are other errors, though.
Also consider removeX = reverse . dropWhile ('X'==) . reverse for better efficiency. Lists are singly-linked, so accesses and modifications at the end are relatively expensive.
Here is an example of what I wanted to do.
let b = ["this","is","a","test!"]
"xx" ++ (b!!3)
This will give me "xxtest!"
Basically if the list contains any string with an exclamation mark then "xx" will be added to this specific string. My questions is how to implement this into a correct function.
Currently I got this
replaceElement [] = []
replaceElement (x:xs) =
if '!' `elem` x
then ["xx"] ++ x : replaceElement xs
else x: replaceElement xs
But this function will just add "xx" into list as an element, it won't be added to the specific string in the list. How can I use "xx" ++ (b!!x) where x is the position of the string with an exclamation mark.
The expression
["xx"] ++ x : replaceElement xs
is actually parsed as
["xx"] ++ (x : replaceElement xs)
which does just what you described: inserts "xx" into the resulting list. What you want to do instead, is:
("xx" ++ x) : replaceElement xs
The crucial thing is how ["xx"] ++ x : replaceElement xs is parsed. This is determined by the fixities of the operators:
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> :info :
-- ...
infixr 5 :
Prelude> :i ++
(++) :: [a] -> [a] -> [a] -- Defined in ‘GHC.Base’
infixr 5 ++
So, both : and ++ are right-associative operators, with the same precedence. Right-associative means, a : b : c is parsed as a : (b : c), instead of (a : b) : c (as would be the case for left-associative infixl). Due to the equal precedence, this still holds if you mix : and ++, i.s.
["xx"] ++ x : replaceElement xs ≡ ["xx"] ++ (x : replaceElement xs)
IOW, you're just prepending ["xx"] to the whole result, but the individual elements never get in contact with "xx". To achieve that, you need to group "xx" with x. The extra brackets are unnecessary then (in fact these could have tipped you off: wrapping "xs" in an extra layer means you're not working of the string-level anymore as intended, but on the list-of-string level).
A better alternative would of course be to not do any manual recursion: you're simply applying the same operation to all elements of a list; that's what map is there for:
replaceElement = map $ \x -> if '!'`elem`x
then "xx"++x
else x
You may also use map with a helper function like;
addxx :: [String] -> [String]
addxx = map checkBang
where checkBang s | last s == '!' = "xx" ++ s
| otherwise = s
I would like to create a function that produces two outputs.
Please consider the following example:
I built two functions that, given a list of integers, return a list of elements in even position and elements in odd position.
let rec alternate1 lst =
match lst with
[] -> []
| [x] -> []
| x::y::xs -> y::(alternate1 xs)
let rec alternate2 lst =
match lst with
[] -> []
| [x] -> [x]
| x::y::xs -> x::(alternate2 xs)
And here everything is fine. Now, the problem: I would like to create a single function alternate that returns both lists with signature alternate: int list-> (int list * int list).
let rec alternate lst =
match lst with
[] -> []
| [x] -> []
| [x::y] -> [y]
(*My attempts:*)
| x::y::xs -> ((y::alternate xs), (x::alternate xs))
| x::y::xs -> [(y::alternate xs); (x::alternate xs)]
| x::y::xs -> ((y::alternate xs) && (x::alternate xs))
So far, no solution worked. I am pretty sure the problem is even silly, but my reference did not help me to solve the problem.
Since you're calling alternate recursively, the recursive call will also return you two outputs, so of course you can't treat that tuple as a list - as in y::alternate xs.
You have to first take the tuple apart, process the parts separately, and recombine them into a tuple before returning:
let nextXs, nextYs = alternate xs
x::nextXs, y::nextYs
And then, your base cases should also return two outputs - otherwise your function has unclear return type:
| [] -> [], []
| [x] -> [x], []
| [x; y] -> [x], [y]
(also note that your match case [x::y] actually matches a list of lists, which contains exactly one list, in which the first element will be named x, and the tail of the list will be named y. In order to match a list of exactly two elements, use [x; y] or x::y::[])
Combining it together:
let rec alternate lst =
match lst with
| [] -> [], []
| [x] -> [x], []
| [x; y] -> [x], [y]
| x::y::rest ->
let nextXs, nextYs = alternate rest
x::nextXs, y::nextYs
Also: technically, the [x; y] base case is not needed, because it would be covered by the last case just fine.
Fyodor's answer is complete (as usual)
So I just wanted to add a tail-recursive version of his code (along with some reduction) to those who wanted to know how to make it tail-recursive (using continuation-passing style)
let alternate xs =
let aux cont even odd (evens, odds) = cont (even :: evens, odd :: odds)
let rec loop cont = function
| [] | [_] as xs -> cont (xs, [])
| even :: odd :: xs -> loop (aux cont even odd) xs
loop id xs
Alternatively one can use 2 continuation for each side list, but here I think it's not so useful as both sides are manipulated each time, but anyway
let alternate xs =
let aux cont x xs = cont (x :: xs)
let rec loop evenCont oddCont = function
| [] | [_] as xs -> evenCont xs, oddCont []
| even :: odd :: xs -> loop (aux evenCont even) (aux oddCont odd) xs
loop id id xs
I'm beginning to learn Haskell with "Learn You a Haskell for Great Good!" and I've made a strange mistake, which I can't find the reason for.
Here is the code I typed:
let xs = [if x < 3 then "bang" else "boom" | x <- xs]
And the the text of the error in GHCi:
No instance for (Num [Char])
arising from the literal `3'
Possible fix: add an instance declaration for (Num [Char])
In the second argument of `(<)', namely `(3)'
In the expression: x < (3)
In the expression: if x < (3) then "bang" else "boom"
But when I type:
let boom xs = [if x < 3 then "bang" else "boom" | x <- xs]
which is the example of the book, I don't have any problem.
Could someone explain my mistake?
Your definition of xs is recursive, that is you're using xs inside its own definition. I don't think that's what you intended.
Since you're using "bang" and "boom" inside the list comprehensions, Haskell knows that xs must be a list of strings (because xs is equal to the result of the list comprehension). Further you say that x is an element of xs (x <- xs), so x must be a String (a.k.a. [Char]). However you do x < 3, which implies that x is a number. The error message means "a String is not a number".
Try to give the expression a type.
xs = [if x < 3 then "bang" else "boom" | x <- xs]
So xs is a list, we don't know yet what type its elements have, so let's look at that next. The list elements are
if x < 3 then "bang" else "boom"
which is an expression of type String (aka [Char]).
So xs :: [String]. Since the x from the expression describing the list elements is taken from the list xs itself, it is a String too, and is used in the comparison
if x < 3
Now, 3 is an integer literal, thus it is polymorphic and has type
3 :: Num a => a
So from the expression x < 3, we have
a Num constraint from the literal,
the type String from the fact that x is drawn from a list of Strings.
Thus we need a Num instance for String to have a well-typed expression.
Usually, there is no Num instance for String (what would a useful one look like?), so you get a type error.
If xs is the argument of a function,
boom xs = [if x < 3 then "bang" else "boom" | x <- xs]
there is no reason why the type of x should be String, hence that works.
let xs = ...
means xs equals a list of "bang"s and/or "boom"s, but the condition states that those elements should be tested for <3, which is usually done with numbers, not strings.
let boom xs =...
equates the function 'boom' with the right hand side of the equation, where the parameter 'xs' is the list from which the elements to be tested for <3 are drawn.