I have a list of lists like so:
[["BBBBBBBB",
"BWFFFPFGB",
"BWFFFPFGB",
"BWFFMPFGB",
"BWFFFPF_B",
"BWFFFPF6B",
"BBBBBBB"]]
I've done a little research and have found out how to access individual elements using the !! operator. But when it comes to searching for a certain element 'M' I'm not sure how to go about that. My friend said I need to use something like (x:xs):xss on a list, but when I try this in the WinGHCi haskell program I get this.
Prelude> let list = [["BBBBBBBB",
"BWFFFPFGB",
"BWFFFPFGB",
"BWFFMPFGB",
"BWFFFPF_B",
"BWFFFPF6B",
"BBBBBBB"]]
Prelude> head(x:xs):xss
<interactive>:192:2: Not in scope: `x'
<interactive>:192:4: Not in scope: `xs'
<interactive>:192:8: Not in scope: `xss'
I understand that I declare the name as list and not x:xs but even when I declare it as x:xs I still get the errors. I'm probably still a little new to haskell to really understand what to do so I may be going about this way wrong.
I've looked here Replace individual list elements in Haskell? because eventually I want to replace the M with something different but I'm not completely sure how I would implement that.
Any help/guidance is appreciated, thanks!
First let's see how to replace a W with M
charWM :: Char -> Char
charWM 'W' = 'M' -- If you see W, put M.
charWM x = x -- If you see anything else, put it back as is.
You can rewrite that function how you like by adding other letter transformations.
Now let's make that work over a list. There's a great function map :: (a ->b) -> [a] -> [b] that lets you apply a function on every element on a list.
stringWM :: String -> String
stringWM xs = map charWM xs -- do charWM to everything in xs.
For example stringWM "QWERTY WILL WIN" = "QMERTY MILL MIN"
Next we can do that to a list of lists:
lolWM :: [String] -> [String]
lolWM xss = map stringWM xss
(String is a type synonym for [Char].)
Let's test that out in ghci:
*Main> list'
["BBBBBBBB","BWFFFPFGB","BWFFFPFGB","BWFFMPFGB","BWFFFPF_B","BWFFFPF6B","BBBBBBB"]
*Main> lolWM list'
["BBBBBBBB","BMFFFPFGB","BMFFFPFGB","BMFFMPFGB","BMFFFPF_B","BMFFFPF6B","BBBBBBB"]
All good.
Your example wasn't exactly list', it was [list'] which has 1 element, so to work on that we'd need to map lolWM. Often we wouldn't bother writing stringWM or lolWM and go directly to lists of lists of lists, if that's what we needed:
lololWM = (map.map.map) charWM
map.map.map means map the map of the map. You can allow that to blow your mind a little, or you can just say list of list of list of Char, so map map map - one map per list level.
In the future, maybe you'll want to replace W with Strings instead of characters.
rewriteChar :: Char -> String
rewriteChar 'W' = "--^--"
rewriteChar x = [x] -- put x in a list to make it a string
This time, map isn't enough: map rewriteChar "QWERTY WILL WIN" gives
["Q","--^--","E","R","T","Y"," ","--^--","I","L","L"," ","--^--","I","N"]
We could use concat on that to flatten it into a single list, but it's more fun to do
rewriteString = concatMap rewriteChar
So now rewriteString "QWERTY WILL WIN" give us "Q--^--ERTY --^--ILL --^--IN".
For more mindblowing things to try, there's "QWERTY WILL WIN" >>= rewriteChar and "Hello Mum" >>= \x -> [x,x,x]
First of all, virtually all "variables" in Haskell are immutable, so there's no "changing a list", there are modified copies.
Second, you need to find an element by some criteria. To do that, you need to traverse a list. - This can be done using recursion. Filtering can be done using a function passed as an argument of your traversing function (this function must take an element and return a boolean value).
Try to put the above together and make your own function. Start with a type signature, it shows what you want to do: to take a list of Char (it's better to generalize to a generic type) and a function which possibly changes an element and return a modified list:
replaceFunc :: (Char -> Char) -> String -> String
Also, read http://www.haskell.org/haskellwiki/How_to_work_on_lists , there's a hint there how to apply some function to specific elements only.
Related
I've written a function which search through a list of int-list to return the index of the list with an specific length by using pattern-matching:
let rec search x lst i = match lst with
| [] -> raise(Failure "Not found")
| hd :: tl -> if (List.length hd = x) then i else search x tl (i+1)
;;
For example:
utop # search 2 [ [1;2];[1;2;3] ] 0 ;;
- : int = 0
Is there a way to write a function with the same functionality using fold.left ?
What does List.fold_left actually do?
It takes (in reverse order to the order of arguments) a list, an initial value, and a function that works on that initial value and the first element in the list. If the list is empty, it returns the initial value. Otherwise it uses the function to update the initial value by way of recursion and works on the tail of the list.
let rec fold_left f init lst =
match lst with
| [] -> init
| x::xs -> fold_left f (f init x) xs
Now, what information do you need to keep track of as you iterate? The index. Easy enough.
But, what if you don't actually find a list of that length? You need to keep track of whether you've found one. So let's say we use a tuple of the index and a boolean flag.
Your function you pass to fold_left just needs to determine if a match has been found no update is necessary. Essentially we just no-op over the rest of the list. But, if we haven't found a match, then we need to test the current sublist's length and update the init value accordingly.
#glennsl (in a comment) and #Chris already explained that you may use List.fold_left but that it’s not the right tool for the job, because it processes the whole list whereas you want to stop once an occurrence is found. There are solutions but they are not satisfying:
(#Chris’ solution:) use a folding function that ignores the new elements once an occurrence has been found: you’re just wasting time, walking through the remaining tail for nothing;
evade the loop by throwing and catching an exception: better but hacky, you’re working around the normal functioning of List.fold_left.
I just mention that there is a generic function in the standard library that matches your situation almost perfectly:
val find : ('a -> bool) -> 'a list -> 'a
find f l returns the first element of the list l that satisfies the predicate f.
Raises Not_found if there is no value that satisfies f in the list l.
However it does not return the index, unlike what you are asking for. This is a deliberate design choice in the standard library, because list indexing is inefficient (linear time) and you shouldn’t do it. If, after these cautionary words, you still want the index, it is easy to write a generic function find_with_index.
Another remark on your code: you can avoid computing the lengths of inner lists fully, thanks to the following standard function:
val compare_length_with : 'a list -> int -> int
Compare the length of a list to an integer. compare_length_with l len is equivalent to compare (length l) len, except that the computation stops after at most len iterations on the list.
Since 4.05.0
So instead of if List.length hd = x, you can do if List.compare_length_with hd x = 0.
I'm fairly new to Haskell and functional programming in general.
This seems like such a simple problem but I'm struggling with the syntax.
I want to take a list of ints as input, if it is null return a null list, and if it is not null then use the map function to add five to every element.
This is my code so far but it produces lots of errors. Any suggestions?
addFive :: [a] -> [a]
addFive [] = []
addFive a = map(+5)
You can use
addFive = map (+5)
or
addFive a = map (+5) a
As map works on empty list, explicit implementation for empty list is not required.
You are thinking along the right lines, but there are a couple of issues.
The code you have shown will complain about a type error. This is because the type of map (+5) is [a] -> [a], but you want just [a]. To fix this you just need to change that line to
addFive a = map (+5) a
Look at the types and think about why this works.
You may also have tried this:
addFive :: [a] -> [a]
addFive [] = []
addFive = map(+5)
This gives you a different error because every version of a function like this needs to have the same number of arguments. Your null case takes one argument, so the other one has to take an argument too.
However you don't need the null case. map already has that built in. So what you actually need is
addFive :: [a] -> [a]
addFive = map (+5)
By the way, one stylistic point. In Haskell we use a, b etc for type variables, but x, xs, y etc for value variables. So the version above would be more idiomatic with
addFive xs = map (+5) xs
I am to use combinators and no for/while loops, recursion or defined library functions from F#'s List module, except constructors :: and []
Ideally I want to implement map
I am trying to write a function called llength that returns the list of the lengths of the sublists. For example llength [[1;2;3];[1;2];[1;2;3]] should return [3;2,3]. I also have function length that returns the length of a list.
let Tuple f = fun a b -> f (a, b)
let length l : int =
List.fold (Tuple (fst >> (+) 1)) 0 l
currently have
let llength l : int list =
List.map (length inner list) list
Not sure how I should try accessing my sublists with my restraints and should I use my other method on each sublist? any help is greatly appreciated, thanks!
Since this is homework, I don't want to just give you a fully coded solution, but here are some hints:
First, since fold is allowed you could implement map via fold. The folding function would take the list accumulated "so far" and prepend the next element transformed with mapping function. The result will come out reversed though (fold traverses forward, but you prepend at every step), so perhaps that wouldn't work for you if you're not allowed List.rev.
Second - the most obvious, fundamental way: naked recursion. Here's the way to think about it: (1) when the argument is an empty list, result should be an empty list; (2) when the argument is a non-empty list, the result should be length of the argument's head prepended to the list of lengths of the argument's tail, which can be calculated recursively. Try to write that down in F#, and there will be your solution.
Since you can use some functions that basically have a loop (fold, filter ...), there might be some "cheated & dirty" ways to implement map. For example, via filter:
let mymap f xs =
let mutable result = []
xs
|> List.filter (fun x ->
result <- f x :: result
true)
|> ignore
result |> List.rev
Note that List.rev is required as explained in the other answer.
So I'm trying to write some minimal code to put two lists of strings together, and to do this I thought it was best to use the haskell map function.
Essentially I want to be able to do adders ["1","2"] ["3","4"] = ["1","2","3","4"]
So I have a function called adder, which takes a list, then adds a string to that list and returns the new list. Then I have a function called adders which replicates the adder function, but adds a list of strings instead of just one string, however at the moment it produces multiple lists instead of one list.
I thought
adder :: [String] -> String -> [String]
adder y x = y ++ [x]
adders y x = map (adder y) x
would work, but this just gives a list of two lists
[["1","2","3"],[["1","2","4"]]
How is the best way to go about this?
I thought it was best to use the haskell map function
No. map f applies f to every element of your list. But you don't want to change the elements at all, you want to change the list itself. That, however, is out of scope of the things that are possible with map. map cannot add more elements, neither can it remove some.
If you want to concatenate two lists, simply use ++:
adders :: [a] -> [a] -> [a]
adders x y = x ++ y
I am given an array of Char and have to translate it to Moves (as shown below)
data Move = N | S | W | E | X
newtype Moves = Moves [Move]
createMoves:: [Char]-> Moves
createMoves (x:xs) = if xs==[] then Moves [createMove(x)]
else Moves [createMove (x)]
createMove:: Char-> Move
createMove (x) = if x=='N' then N
else if x=='S' then S
else if x=='W' then W
else if x=='E' then
else X
However, I am only succeeding in getting the first item of the list. I have tried a number of ways to make createMoves recursive but I can't get it right. Could you please guide me?
Branches of your if statement are the same, so it does nothing.
When programming recursive functions, there are two cases.
The basic one, you should declare createMoves [] = [].
The recursive is a little more complicated; basically, for each x you create a move that is the first element appended to a list built using a recursive call on xs.
A simpler way is to use the map function. You can also look at its implementation.
By the way, for createMove you could use pattern matching instead of many ifs.
Your problem seems to be centering on combining the result of the recursive call on xs with the result of createMove x. So, let's just introduce a helper function which is going to take care of that!
createMoves:: [Char]-> Moves
createMoves (x:xs) = if xs==[] then Moves [createMove x]
else createHelper (createMove x) (createMoves xs)
Now, what should the type of createHelper be? Its first argument is a Move and the second is a Moves, and it should put the first argument in front of the list of Moves contained in the second, and 'repack' it in a value of type Moves. To get at the list of Moves you need to use pattern matching, like so:
createHelper :: Move -> Moves -> Moves
createHelper m (Moves ms) = Moves (m:ms)
That should do the trick, but all this matching on the Moves constructor and then reapplying it is a bit silly, and potentially inefficient. A better approach is to convert the [Char] one-by-one to [Move] and only at the end tacking the Moves constructor on. That leads to something like (still in keeping with your original idea):
createMoves :: [Char] -> Moves
createMoves cs = Moves (createMoveList cs)
createMoveList :: [Char] -> [Move]
createMoveList (x:xs) = if xs == [] then [] else createMove x : createMoveList xs
createMoveList is a pattern that comes up very often in Haskell, namely that of applying a function (in this case, createMove) to each element in a list. This is the essence of the map function (which I'm sure you'll get to very soon in your lessons, if you haven't already!).
If you use that, you can also get rid of the problem that createMoves fails when given an empty list. So the solution I would go with is:
createMoves :: [Char] -> Moves
createMoves cs = Moves (map createMove cs)
or
createMoves = Moves . map createMove
but that's another story!
Your createMoves function only operates on one element of the list it's given.
Try using the map function. On other words, start your function with:
createMoves list = Moves (map
[...]
You may wish to use Guards (i.e. |) instead of if, then and else.
First, you should remove the newtype statement; if you want the list to print, just have the Move type derive Show.
Next, you can remove the explicit recursion in the createMoves function by using map. For future reference, you can look for functions by name and type signature on Hoogle.
Finally, you can use pattern matching to eliminate all the equality tests against constants. An irrelevant example using the Move type is
isN :: Move -> Bool
isN N = True
isN _ = False
Note that the _ character means "ignore this value". If you haven't covered pattern matching yet, then guards might still be better than nested ifs.