I'm having a few issues with trees, I was trying to make a simplified Family tree (genealogy tree) where I start with only 1 person, let's say Grandpa Bob, I'll try my best drawing this:
BOB
|
/ \
SIMON RUDY
/ \ / \
ROBBIE MARTHA TOM ISABEL
So, Grandpa Bob had 2 kids with Grandma(which doesn't matter here), Simon and Rudy, then Simon and Rudy both had 2 kids each (only 1 parent matters again), note that this is not necessarily the tree I want to make but only an example which can be used by you guys to help me out. I want to have it as a data Family, then have a function that initiates the "root" which will be Grandpa Bob and then have another function that will let me add someone to the tree, as in add Simon descending from Bob.
So far this is what I have atm(I've tried other things and changed it all over):
module Geneaology where
data Family a = Root a [Family a] | Empty deriving (Show, Read)
main :: IO()
main = do
root :: String -> Family
root a = ((Root a) [Empty])
Now, this doesn't work at all and gives me a parse error:
t4.hs:9:10: parse error on input ‘=’
I've tried to fix this and change the code around looking for other ways, and saw other posts as well, but didn't make any progress...
I think I made myself clear, thanks in advance xD
You have a syntax error, you can create a function in the main with a let and a lambda, and then use it
data Family a = Root a [Family a] | Empty deriving (Show, Read)
main :: IO()
main = do
let root = (\a -> Root a [Empty])
print(root "Bob")
But you can also define functions outside the main and call them latter:
root :: String -> Family String
root a = Root a [Empty]
main :: IO()
main = do
print(root "Bob")
Related
I am trying to write a code that generates all binary trees with n nodes (so the program has to return a list in which we can find all the different binary trees with n nodes).
Here is the way I represent binary trees :
type 'a tree = Empty | Node of 'a * 'a tree * 'a tree
So I am trying to implement a function all_tree : int -> tree list such that :
all_tree 0 = [Empty]
all_tree 1 = [Node('x',Empty,Empty)]
all_tree 2 = [Node('x',Node('x',Empty,Empty),Empty); Node('x',Empty,Node('x',Empty,Empty))]
...
I tried several ideas but it didn't work out. For example we could try the following :
let rec all_tree result = function
|0 -> r
|s -> all_tree ((List.map (fun i -> Node('x',i,Empty)) result)#(List.map (fun i -> Node('x',Empty,i)) result) ) (s-1)
in all_tree [Empty] (*some number*)
This code doesn't work because it doesn't generate every possibility.
Here is one possible answer.
let rec all_trees = function
| 0 -> [Empty]
| n ->
let result = ref [] in
for i = 0 to n-1 do
let left_side = all_trees i
and right_side = all_trees (n-1-i) in
List.iter
(fun left_tree ->
List.iter
(fun right_tree ->
result := (Node('x', left_tree, right_tree)) :: (!result)
)
right_side
)
left_side
done;
!result
;;
It's pretty simple: a tree with n>0 nodes is a tree with 1 node at the top, and then n-1 nodes below split between a certain number on the left and a certain number on the right. So we loop for i from 0 to n-1 through all possible numbers of values on the left side, and n-i-1 is going to be the number of nodes on the right side. We recursively call all_trees to get the trees with i and n-i-1 nodes, and simply aggregate them.
Notice that it's a very poor implementation. It has everything a recursive function should avoid. See something like this page on recursive implementations of the Fibonacci sequence to see how to improve it (one of the first things to do would be to cache the results rather than recompute the same things many many times).
I do agree with the question's comments though that writing a printer would be step 1 in that kind of project, because it's really annoying having to read through messy things like [Node ('x', Node ('x', Empty, Node ('x', Node ('x', Empty, Empty), Empty)), Empty);. Naming variables better would also make it easier for people to read your code and will increase the chance someone will help you. And generally, listening to the comments when people give you advice on how to properly ask your questions will make it easier for you to get answers both right now and in your future questions. For instance, in my own code, I used i as the loop index. It makes sense to me while I'm coding it, but when you read the code, maybe you would have preferred to read something like left_side_nodes or something like that, which would have made it obvious what this variable was supposed to do. It's the same in your own scenario: you could call i something like subtree or maybe something even more explicit. Actually, properly naming it could make you realize what's wrong with your code. Often, if you can't properly name a variable, it's that you don't really understand what it's doing (even local variables).
I'm teaching myself OCaml and I sometimes need to create a function where I'm not really sure what the proper solution should be. Here's one that I'm a little confused about.
I need a function that will prompt the user for individual float values and return everything entered in a float list. I can create this function but I'm not sure if its the proper/best way to do it in Ocaml.
Here's my attempt.
let rec get_floats() =
match
(
try Some(read_float())
with
| float_of_string -> None
)
with
| None -> []
| Some s -> s :: get_floats();;
This code works buts I'm at a loss deciding if its a 'proper OCaml' solution. Note, to exit the function and return the float list just enter a non-integer value.
(I hope that) this is a simple peephole rewrite involving no thought whatsoever of the function in your question:
let rec get_floats() =
try
let f = read_float() in (* as suggested by Martin Jambon *)
f :: (get_floats())
with
| float_of_string -> []
The idea I tried to apply here is that you do not need to convert the success/failure of read_float into an option that you immediately match: just do what you have to do with the value read, and let the with handle the failure case.
Now that I think of it, I should point out that in both your question and my rewrite, float_of_string is a fresh variable. If you meant to match a specific exception, you failed at it: all exception constructors, like datatype constructors, are Capitalized. You might as well have written with _ -> instead of with float_of_string ->, and a recent version of OCaml with all warnings active should tell you that your function (or mine) binds a variable float_of_string without ever using it.
Thanks everyone for the help. This works.
let rec get_floats() =
try
let x = read_float() in
x :: get_floats()
with
| _ -> [];;
List.iter (fun x -> print_endline(string_of_float x)) (get_floats());;
I have this derived data type AcInfo which consists of the following user created data types
[(AcNo, Name, City, Amnt)]
(all are strings except Amnt which is an Int) what i want is to get a tuple out of the following list by checking the AcNo.
I made the declaration and a bit further, but I am finding it hard to figure out what to do next. The declaration:
accountDetails :: AcInfo -> AcNo -> [Name, City, Amnt]
accountDetails dbase number
Will the use of list comprehension be useful? Furthermore, what would be a good way of going for a solution?
Thanks in advance.
You could do this with list comprehensions pretty easily:
locateAcct :: AcNo -> [(AcNo, Name, City, Amnt)] -> (AcNo, Name, City, Amnt)
locateAcct account db = head [ tup | tup#(ac, _, _, _) <- db, ac == account ]
Of course, by using head, we open ourselves up to the possibility of a failed match. Perhaps a better approach would be to use something like the safe library's version of headMay, which returns Nothing if the list is empty:
locateAcct :: AcNo -> [(AcNo, Name, City, Amnt)] -> Maybe (AcNo, Name, City, Amnt)
locateAcct account db = headMay [ tup | tup#(ac, _, _, _) <- db, ac == account ]
Now if that account doesn't exist, you get Nothing instead of a pattern match failure.
find ((==) target . fst4) : http://zvon.org/other/haskell/Outputlist/find_f.html
where fst4 is a version of fst that takes a 4-tuple. Not sure if it is in a library, but it is easy to write.
I need to scan through a document and accumulate the output of different functions for each string in the file. The function run on any given line of the file depends on what is in that line.
I could do this very inefficiently by making a complete pass through the file for every list I wanted to collect. Example pseudo-code:
at :: B.ByteString -> Maybe Atom
at line
| line == ATOM record = do stuff to return Just Atom
| otherwise = Nothing
ot :: B.ByteString -> Maybe Sheet
ot line
| line == SHEET record = do other stuff to return Just Sheet
| otherwise = Nothing
Then, I would map each of these functions over the entire list of lines in the file to get a complete list of Atoms and Sheets:
mapper :: [B.ByteString] -> IO ()
mapper lines = do
let atoms = mapMaybe at lines
let sheets = mapMaybe to lines
-- Do stuff with my atoms and sheets
However, this is inefficient because I am maping through the entire list of strings for every list I am trying to create. Instead, I want to map through the list of line strings only once, identify each line as I am moving through it, and then apply the appropriate function and store these values in different lists.
My C mentality wants to do this (pseudo code):
mapper' :: [B.ByteString] -> IO ()
mapper' lines = do
let atoms = []
let sheets = []
for line in lines:
| line == ATOM record = (atoms = atoms ++ at line)
| line == SHEET record = (sheets = sheets ++ ot line)
-- Now 'atoms' is a complete list of all the ATOM records
-- and 'sheets' is a complete list of all the SHEET records
What is the Haskell way of doing this? I simply can't get my functional-programming mindset to come up with a solution.
First of all, I think that the answers others have supplied will work at least 95% of the time. It's always good practice to code for the problem at hand by using appropriate data types (or tuples in some cases). However, sometimes you really don't know in advance what you're looking for in the list, and in these cases trying to enumerate all possibilities is difficult/time-consuming/error-prone. Or, you're writing multiple variants of the same sort of thing (manually inlining multiple folds into one) and you'd like to capture the abstraction.
Fortunately, there are a few techniques that can help.
The framework solution
(somewhat self-evangelizing)
First, the various "iteratee/enumerator" packages often provide functions to deal with this sort of problem. I'm most familiar with iteratee, which would let you do the following:
import Data.Iteratee as I
import Data.Iteratee.Char
import Data.Maybe
-- first, you'll need some way to process the Atoms/Sheets/etc. you're getting
-- if you want to just return them as a list, you can use the built-in
-- stream2list function
-- next, create stream transformers
-- given at :: B.ByteString -> Maybe Atom
-- create a stream transformer from ByteString lines to Atoms
atIter :: Enumeratee [B.ByteString] [Atom] m a
atIter = I.mapChunks (catMaybes . map at)
otIter :: Enumeratee [B.ByteString] [Sheet] m a
otIter = I.mapChunks (catMaybes . map ot)
-- finally, combine multiple processors into one
-- if you have more than one processor, you can use zip3, zip4, etc.
procFile :: Iteratee [B.ByteString] m ([Atom],[Sheet])
procFile = I.zip (atIter =$ stream2list) (otIter =$ stream2list)
-- and run it on some data
runner :: FilePath -> IO ([Atom],[Sheet])
runner filename = do
resultIter <- enumFile defaultBufSize filename $= enumLinesBS $ procFile
run resultIter
One benefit this gives you is extra composability. You can create transformers as you like, and just combine them with zip. You can even run the consumers in parallel if you like (although only if you're working in the IO monad, and probably not worth it unless the consumers do a lot of work) by changing to this:
import Data.Iteratee.Parallel
parProcFile = I.zip (parI $ atIter =$ stream2list) (parI $ otIter =$ stream2list)
The result of doing so isn't the same as a single for-loop - this will still perform multiple traversals of the data. However, the traversal pattern has changed. This will load a certain amount of data at once (defaultBufSize bytes) and traverse that chunk multiple times, storing partial results as necessary. After a chunk has been entirely consumed, the next chunk is loaded and the old one can be garbage collected.
Hopefully this will demonstrate the difference:
Data.List.zip:
x1 x2 x3 .. x_n
x1 x2 x3 .. x_n
Data.Iteratee.zip:
x1 x2 x3 x4 x_n-1 x_n
x1 x2 x3 x4 x_n-1 x_n
If you're doing enough work that parallelism makes sense this isn't a problem at all. Due to memory locality, the performance is much better than multiple traversals over the entire input as Data.List.zip would make.
The beautiful solution
If a single-traversal solution really does make the most sense, you might be interested in Max Rabkin's Beautiful Folding post, and Conal Elliott's followup work (this too). The essential idea is that you can create data structures to represent folds and zips, and combining these lets you create a new, combined fold/zip function that only needs one traversal. It's maybe a little advanced for a Haskell beginner, but since you're thinking about the problem you may find it interesting or useful. Max's post is probably the best starting point.
I show a solution for two types of line, but it is easily extended to five types of line by using a five-tuple instead of a two-tuple.
import Data.Monoid
eachLine :: B.ByteString -> ([Atom], [Sheet])
eachLine bs | isAnAtom bs = ([ {- calculate an Atom -} ], [])
| isASheet bs = ([], [ {- calculate a Sheet -} ])
| otherwise = error "eachLine"
allLines :: [B.ByteString] -> ([Atom], [Sheet])
allLines bss = mconcat (map eachLine bss)
The magic is done by mconcat from Data.Monoid (included with GHC).
(On a point of style: personally I would define a Line type, a parseLine :: B.ByteString -> Line function and write eachLine bs = case parseLine bs of .... But this is peripheral to your question.)
It is a good idea to introduce a new ADT, e.g. "Summary" instead of tuples.
Then, since you want to accumulate the values of Summary you came make it an istance of Data.Monoid. Then you classify each of your lines with the help of classifier functions (e.g. isAtom, isSheet, etc.) and concatenate them together using Monoid's mconcat function (as suggested by #dave4420).
Here is the code (it uses String instead of ByteString, but it is quite easy to change):
module Classifier where
import Data.List
import Data.Monoid
data Summary = Summary
{ atoms :: [String]
, sheets :: [String]
, digits :: [String]
} deriving (Show)
instance Monoid Summary where
mempty = Summary [] [] []
Summary as1 ss1 ds1 `mappend` Summary as2 ss2 ds2 =
Summary (as1 `mappend` as2)
(ss1 `mappend` ss2)
(ds1 `mappend` ds2)
classify :: [String] -> Summary
classify = mconcat . map classifyLine
classifyLine :: String -> Summary
classifyLine line
| isAtom line = Summary [line] [] [] -- or "mempty { atoms = [line] }"
| isSheet line = Summary [] [line] []
| isDigit line = Summary [] [] [line]
| otherwise = mempty -- or "error" if you need this
isAtom, isSheet, isDigit :: String -> Bool
isAtom = isPrefixOf "atom"
isSheet = isPrefixOf "sheet"
isDigit = isPrefixOf "digits"
input :: [String]
input = ["atom1", "sheet1", "sheet2", "digits1"]
test :: Summary
test = classify input
If you have only 2 alternatives, using Either might be a good idea. In that case combine your functions, map the list, and use lefts and rights to get the results:
import Data.Either
-- first sample function, returning String
f1 x = show $ x `div` 2
-- second sample function, returning Int
f2 x = 3*x+1
-- combined function returning Either String Int
hotpo x = if even x then Left (f1 x) else Right (f2 x)
xs = map hotpo [1..10]
-- [Right 4,Left "1",Right 10,Left "2",Right 16,Left "3",Right 22,Left "4",Right 28,Left "5"]
lefts xs
-- ["1","2","3","4","5"]
rights xs
-- [4,10,16,22,28]
I have just typed in the RandomState example from real world haskell. It looks like this:
import System.Random
import Control.Monad.State
type RandomState a = State StdGen a
getRandom :: Random a => RandomState a
getRandom =
get >>= \gen ->
let (val, gen') = random gen in
put gen' >>
return val
getTwoRandoms :: Random a => RandomState (a, a)
getTwoRandoms = liftM2 (,) getRandom getRandom
It works, but the result doesn't get displayed. I get the error message:
No instance for (Show (RandomState (Int, Int)))
arising from a use of `print' at <interactive>:1:0-38
Possible fix:
add an instance declaration for (Show (RandomState (Int, Int)))
In a stmt of a 'do' expression: print it
I am having some trouble adding an instance for Show RandomState. Can anyone show me how this is done?
Thanks.
For the sake of being explicit, as jberryman and the comments on the question imply: Something of type RandomState (a, a) is a function, not a value. To do anything with it, you want to run it with an initial state.
I'm guessing you want something like this:
> fmap (runState getTwoRandoms) getStdGen
((809219598,1361755735),767966517 1872071452)
This is essentially what the runTwoRandoms function a bit further in RWH is doing.
Since RandomState is a synonym for State and there isn't an instance of show defined for State, you won't be able to show it.
You would also not be able to derive show because State is just a wrapper for a function and Haskell has no way to define a show for functions that would be useful:
Prelude> show (+)
<interactive>:1:0:
No instance for (Show (a -> a -> a))
arising from a use of `show' at <interactive>:1:0-7
Possible fix: add an instance declaration for (Show (a -> a -> a))
In the expression: show (+)
In the definition of `it': it = show (+)
EDIT: Forgot to add the other piece: GHCi is giving you that error because it uses show behind the scenes on the expressions you enter... REPL and all that.