I am learning Haskell and I have a problem where if given a list of a list of a list of Strings I have to find the total number of Strings in the entire initial list. My though process was to convert the entire initial list into a one dimensional list and get the length, however I can seem to figure it out.
What I have so far:
type Word = String
type Line = [Word]
type Page = [Line]
type Doc = [Page]
numWords :: Doc -> Line -> Word -> Int
I need to find the number of Words and I'm not sure if this is even the best way to go about this type of problem, but I am at a loss for ideas.
Any help would be much appreciated.
Thank you.
This is quite a simple problem.
If we have a look at the types, it becomes easy:
type Word = String
type Line = [String]
type Page = [[String]]
type Doc = [[[String]]]
It's not too difficult to get the length of a Line:
lenLine x = length x
The Page is just the sum of all the inner lengths:
lenPage xs = sum $ map lenLine xs
And we can use the same kind of pattern for Doc:
lenDoc xs = sum $ map lenPage xs
As for your final function , just use all the others:
numWords :: Doc -> Page -> Line -> Int
numWords dc pg ln = lenDoc dc + lenPage pg + lenLine ln
Remember that a type synonym doesn't mean that the type is actually different; you can use the same functions.
Related
I have these defined types
type Name = string
type Flow = int
type River = R of Name * Flow * River list
type Tributaries = River list
And i want to declare a function contains n r that returns a boolean value if n is contained in River or any of it's branches/Tributaries. and i've came up with this so far
let rec contains (n:Name)(r:River) =
match r with
|R(Name,_,_) when Name = n -> true
|R(_,_,Tr) -> contains n Tr
|_ -> false
However F# cant recoginze Tr as Tr is a list and not of type river so i can't pass it in of course, how can i do this in a nice and clean way without declaring two seperate functions to help?
Gus's answer fixes the specific issue and answers the question, but often things like this are slightly more elegant if work on a list of rivers (a 'forest' of trees) rather than a single one.
The solution is a little odd because the recursive step creates a new river to search in based on the tail of the tributaries of the input river, perfectly valid, but if feels a little odd.
first lets tidy up the types
type Name = string
type Flow = int
type Tributaries = River list
and River = R of Name * Flow * Tributaries
now we write something that feels harder than what you want to do, but is in fact (to me) intuitively easier to understand, i.e. you check the tail of the passed list AND you check the tributaries into the current river.
let rec containsTributaries (n: Name) (rs: River list) =
match rs with
| R (name, _, _) :: _ when name = n -> true
| R (_, _, tribs) :: tail -> containsTributaries n tail || containsTributaries n tribs
| _ -> false
then searching for a single river is trivial
let rec contains (n: Name) (river: River) =
containsTributaries n [ river ]
(but basically this is the same answer as Gus's)
The problem is Tr is a list and your function expect a River structure.
So, you would have to decompose the list in head and tail and check on both.
You can do that by changing the second match:
|R(_,_,Tr) -> contains n Tr
to
| R (name, f, x::xs) -> contains n x || contains n (R (name, f, xs))
Of course there are more efficient ways of doing this and you can use built in functions, but if you're learning this is the solution you want to come up in first place.
I'm trying to convert a list with a specified width to array array.
For example, i want to convert this :
int list = [97; 114; 110; 97; 117; 100; 2]
to
int array array = [| [|97; 114; 110|]; [|97; 117; 100|]; [|2; 0; 0|] |]
I am not used to ocaml so I tried to use this code :
let split list width =
let rec aux i acc = function
| [] -> List.rev acc, []
| h :: t as l ->
if i = 0
then List.rev acc, l
else aux (i-1) (h :: acc) t in
aux width [] list;;
If you want to code in a language you have to get used to it :) You have to spend a couple of hours and read at least the intoduction to OCaml. The first chapter would be enough to be able to solve your example.
In your particular example, (which I took the liberty to reindent, to make it more readable), the variable n in aux n [] list is unbound. Indeed, what n is supposed to mean? Another tip, is that the width parameter of your function is not used in the body of your function. You probably already get it... but do not rush to fix it. First, read the introductory course to OCaml :)
I would work backwards on this problem.
First I would create a function which takes a list, a padding value and the number of times that padding must be applied. Something like this:
val add_padding: int -> int -> int list -> int list
Next I would create a function which takes a list and a width and returns a new list and the remainder of the list passed in... This should fail if the passed in list is too short. Something like:
val create_new_list: int -> 'a list -> 'a list * 'a list
With these two functions, you should be able to split your input list.
Hi I've got a list on Haskell with close to 10^15 Int's in it and I'm trying print the length of the list.
let list1 = [1..1000000000000000] -- this is just a dummy list I dont
print list1 length -- know the actual number of elements
printing this takes a very long time to do, is there another way to get the number of elements in the list and print that number?
I've occasionally gotten some value out of lists that carry their length. The poor man's version goes like this:
import Data.Monoid
type ListLength a = (Sum Integer, [a])
singletonLL :: a -> ListLength a
singletonLL x = (1, [x])
lengthLL :: ListLength a -> Integer
lengthLL (Sum len, _) = len
The Monoid instance that comes for free gives you empty lists, concatenation, and a fromList-alike. Other standard Prelude functions that operate on lists like map, take, drop aren't too hard to mimic, though you'll need to skip the ones like cycle and repeat that produce infinite lists, and filter and the like are a bit expensive. For your question, you would also want analogs of the Enum methods; e.g. perhaps something like:
enumFromToLL :: Integral a => a -> a -> ListLength a
enumFromToLL lo hi = (fromIntegral hi-fromIntegral lo+1, [lo..hi])
Then, in ghci, your example is instant:
> lengthLL (enumFromToLL 1 1000000000000000)
1000000000000000
How can I add a list to a list of lists? Say I want to add itemz to bagList, which is a list of lists. How can I do that?
bagList itemz = mappend bagList itemz
You might want to consider adding it at the front, this is faster:
bagItem bag item = item : bag
Also it looks like you're coming from an imperative mindset, the way you use bagList before and after the = is not quite right: the expressions before and after the = do not really represent the same construction. Before the = bagItem is used as a function, after the = it's used as some Monoid (which if itemz is a list would also need to be a list).
If you really do want to append the item (this will be slower, because the operation will require going all the way through the list to add the new item at the end, and the whole list will need to be reconstructed) you can do what Christoph suggests or you can go for a recursive formulation something like this:
appendItem :: a -> [a] -> [a]
appendItem i (x:xs) = x : appendItem i xs
appendItem i [] = i : []
If you both want to append and are also worried about performance, you should have a look at difference lists, for example look for the section on difference lists in this chapter in Learn You a Haskell.
Update
From the comments it seems what you are actually looking for is Maps. We can make a Map with each item as a key, and the number of occurrences as the value. In your case it seems this will be a Map String Int.
import Data.List (foldl')
import qualified Data.Map as M
bag :: M.Map String Int
bag = M.empty
addToBag :: M.Map String Int -> [String] -> M.Map String Int
addToBag = foldl' go
where go m i = M.insertWith (+) i 1 m
main = print $ addToBag bag ["a","b","c","a"]
-- fromList [("a",2), ("b", 1), ("c", 1)]
sorry if the questions to basic, but i havent been able to do this for some time. I have created a lists of lists in which the second array contains a parameter that can be either an f or a p. I need to create two new lists of arrays, one containing the items that have the f parameter and the other one containing the p parameter.
edit: trying to explain myself:
I have a list containing a series of facebook publications, and each one of this publications has information, such as what type of publication it is.. they can be either a p (text) or f (picture). What i need to do is to create two separate lists of this publications by the type publication they are.
example of data: [[|"publication0ID", "Poster0ID","TypeofPublication0"|];[|"publication1ID", "Poster1ID","TypeofPublication1"|]]
let data = [[|"publication0ID"; "Poster0ID"; "f"|];[|"publication1ID"; "Poster1ID"; "p"|]]
let texts, pictures =
data
|> List.partition (List.ofArray >> function
| _ :: _ :: "f" :: _ -> true
| _ :: _ :: "p" :: _ -> false
| _ -> failwith "neither f nor p"
)
This will split the lists according to the third "parameter", which you called "TypeOfPublication".
I changed your sample code, because your sub-arrays sub-lists contain only one tuple and judging by your "..." I tought that might be wrong.
To explain:
List.partition splits a list according to a function that is called for every element in the list. When the function returns true, the element will be put into the first list of the result tuple, and into the second list when false.
Since your elements are arrays also lists, it will be checked if the third element in the array list is either "f", which will cause the array list to be put in the texts result, and "p", which will be put into pictures.
If the third element is neither "f" nor "p", an exception will be thrown.
Update for the comment:
If your sub-arrays are always exactly three elements long, you can use this version:
let texts, pictures =
data
|> List.partition (function
| [| _; _; "f" |] -> true
| [| _; _; "p" |] -> false
| _ -> failwith "neither f nor p or wrong array length"
)
Or, you can use the first version and just put List.ofArray >> in between the function keyword and the opening paren so that it reads: List.partition (List.ofArray >> function (I updated the code above as well).
Assuming that your main list is of type (int, string) list list, then if you
let f = 1
let p = 1
you should be able to filter your main_list by using
let f_items = seq {
let! sub_list = main_list
let! (selector, item) = sub_list
if selector == f then
yield item
}
and likewise, to get the "p" items, you would use selector == p.
I had to bring out my F# book to be able to write this code, I haven't used F# for so long! I don't have F# on this computer, so I don't know if the above code actually works.