How can I view the internal representation of Haskell Data.Map?
Also, what kind of data structure is used to implement it?
Is it essentially a red black tree?
Or some kind of heap min?
Here is a simple example that I am interested in dumping to a text file
(or even better, a Graphviz dot representation).
module Main( main ) where
import qualified Data.Map as Map
t = Map.fromList([
(6,"six"),
(2,"two"),
(8,"eight"),
(3,"three"),
(5,"five")])
main = do
putStrLn $ show $ Map.lookup 3 t
putStrLn $ show $ Map.lookup 7 t
Here is a textual dump with showTreeWith:
module Main( main ) where
import qualified Data.Map as Map
t = Map.fromList([
(6,"six"),
(2,"two"),
(8,"eight"),
(3,"three"),
(5,"five")])
main = do
putStrLn $ Map.showTreeWith (\k x -> show (k,x)) True False t
putStrLn $ show $ Map.lookup 3 t
putStrLn $ show $ Map.lookup 7 t
And here is how it looks:
$ ghc main.hs
$ ./main
(6,"six")
+--(3,"three")
| +--(2,"two")
| +--(5,"five")
+--(8,"eight")
Just "three"
Nothing
According to the documentation for Haskell's Data.Map:
The implementation of Map is based on size balanced binary trees (or trees of bounded balance)
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last year.
Improve this question
I have been working through Harvard's CS51 class using materials available online. I'm trying to start the final project and downloaded the necessary files, but when I try to compile them I get the following error:
Error: Module `Unix' is unavailable (required by `Thread')
Command exited with code 2.
Compilation unsuccessful after building 18 targets (15 cached) in 00:00:00.
I have not made any changes to the code I downloaded yet and supposedly I should be able to compile it successfully in its current state. Any ideas why I might be getting this error?
EDIT: Below is the code from the file I downloaded and am trying to compile.
module Ev = Evaluation ;;
module MP = Miniml_parse ;;
module ML = Miniml_lex ;;
module Ex = Expr ;;
open Printf ;;
(* str_to_exp str -- Returns the expression specified by `str` using
the MiniML parser. *)
let str_to_exp (str: string) : Ex.expr =
let lexbuf = Lexing.from_string str in
let exp = MP.input ML.token lexbuf in
exp ;;
(* repl () -- Read-eval-print loop for MiniML, which prompts for and
evaluates MiniML expressions, printing the resulting value. Exits
the loop and terminates upon reading an end-of-file
(control-d). *)
let repl () =
(* lexical analyzer buffer from stdin *)
let lexbuf = Lexing.from_channel stdin in
(* set up the initial environment *)
let env = Ev.Env.empty () in
(* the main LOOP *)
while true do
(try
(* prompt *)
printf "<== %!";
(* READ and parse an expression from the input *)
let exp = MP.input ML.token lexbuf in
(* EVALuate it *)
let res = Ev.evaluate exp env in
(* PRINT the result; in this initial version, the trivial
evaluator just returns the expression unchanged as an
element of the `Env.value` type (found in `expr.ml`), so we
just extract the expression back out and print it *)
match res with
| Val resexp ->
printf "==> %s\n" (Ex.exp_to_abstract_string resexp)
| _ -> failwith "not handling other cases yet"
with
| MP.Error -> printf "xx> parse error\n"
| Ev.EvalError msg -> printf "xx> evaluation error: %s\n" msg
| Ev.EvalException -> printf "xx> evaluation exception\n"
| End_of_file -> printf "Goodbye.\n"; exit 0
);
flush stdout
done
;;
(* Run REPL if called from command line *)
try
let _ = Str.search_forward (Str.regexp "miniml\\.\\(byte\\|native\\|bc\\|exe\\)")
(Sys.argv.(0)) 0 in
repl ()
with Not_found -> () ;;
If I add open Unix it does take care of the error above, but I then get a different error:
26 | let lexbuf = Lexing.from_channel stdin in
^^^^^
Error: This expression has type Unix.file_descr
but an expression was expected of type in_channel
Command exited with code 2.
Generally, you have to explicitly ask to be linked to the Unix module.
The following program:
$ cat main.ml
Unix.gethostname () |> print_endline
would need to be built like this:
$ ocamlfind opt -linkpkg -package unix -o main main.ml; echo $?
0
whereas the bare minimum would fail with a similar error as yours:
$ ocamlopt -o main main.ml; echo $?
File "main.ml", line 1:
Error: No implementations provided for the following modules:
Unix referenced from main.cmx
2
That said, it looks like you're using Core, in which case (as well as most
other cases, actually) you're probably better off with dune:
$ cat dune
(executable
(name main)
(libraries unix))
$ dune build main.exe
$ ./_build/default/main.exe
amam-oy
However, if you ask Dune to link you to Core, Unix is already included
automatically, so the following dune file would also work for the above
program:
$ cat dune
(executable
(name main)
(libraries core))
Just add
open Unix;;
at the very start of your .ml file
Is it possible to create a new environment variable with an alias?
I'm aware that I could set the environment variable as an alias to begin with, but I need it to be dynamic and able to change on the fly.
E.g, I work in Film on different shots at a time, so when I open a program I set the shot through the my environment variable like this:
export shot=abc_123
What I would like to do is not have to type out 'export shot=' and just type 'shot abc_123' in to a shell which would change the env var.
I am using zsh on osx.
Any ideas on how I can integrate this?
We can create a zsh function that implements this in our ~/.zshrc like so:
function setShot() {
export shot="$#"
}
Then, we can call the function, and all params will be set to the shot variable.
Small example:
$
$ which setShot
setShot () {
export shot="$#"
}
$
$ echo $shot
$
$ setShot testShot_1234
$
$ echo $shot
testShot_1234
$
I found this sudo wrapper from Zsh mailing list:
alias sudo='noglob do_sudo '
function do_sudo
{
integer glob=1
local -a run
run=( command sudo )
if [[ $# -gt 1 && $1 = -u ]]; then
run+=($1 $2)
shift ; shift
fi
(($# == 0)) && 1=/bin/zsh
while (($#)); do
case "$1" in
command|exec|-) shift; break ;;
nocorrect) shift ;;
noglob) glob=0; shift ;;
*) break ;;
esac
done
if ((glob)); then
PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" $run $~==*
else
PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" $run $==*
fi
}
It uses $~==* to expand the file patterns. What is this kind of expansion called? Where is it documented? (really have got no idea how to search for this, 'dollar tilde expansion', 'filename expansion', 'tilde expansion' all just gave me some irrelevant results...)
And I noticed that actually $~var also works, e.g.
$ touch foo bar
$ t1='fo*'
$ echo $~t1
foo
$ t2=('fo*' 'ba*')
$ echo $~t2
foo bar
Is it any different from $~==t1? Btw it seems there can be an arbitrary number of =s between $ and variable name, $~=t1 $=~t1 $~=====t1 all look the same.
Thanks to #chepner for the hint. Here's what I found in zshexpn manual:
${=spec}
Perform word splitting using the rules for SH_WORD_SPLIT during the evaluation of spec, but regardless of whether the parameter appears in double quotes; if the `=' is
doubled, turn it off. This forces parameter expansions to be split into separate words before substitution, using IFS as a delimiter. This is done by default in most
other shells.
Note that splitting is applied to word in the assignment forms of spec before the assignment to name is performed. This affects the result of array assignments with the A
flag.
${~spec}
Turn on the GLOB_SUBST option for the evaluation of spec; if the `~' is doubled, turn it off. When this option is set, the string resulting from the expansion will be in‐
terpreted as a pattern anywhere that is possible, such as in filename expansion and filename generation and pattern-matching contexts like the right hand side of the `='
and `!=' operators in conditions.
In nested substitutions, note that the effect of the ~ applies to the result of the current level of substitution. A surrounding pattern operation on the result may can‐
cel it. Hence, for example, if the parameter foo is set to *, ${~foo//\*/*.c} is substituted by the pattern *.c, which may be expanded by filename generation, but
${${~foo}//\*/*.c} substitutes to the string *.c, which will not be further expanded.
So ~ enables globbing which substitutes patterns (specs) with file names. == makes sure that word splitting is disabled for strings in quotes.
For example:
$ touch foo bar
$ spec='fo* ba*'
$ echo $~spec
zsh: no matches found: fo* ba*
$ echo $~=spec
foo bar
$ echo $~==spec
zsh: no matches found: fo* ba*
$ function test1() { printf '1=%s 2=%s\n' $1 $2; }
$ test1 $spec
1=fo* ba* 2=
$ test1 $~spec
zsh: no matches found: fo* ba*
$ test1 $~=spec
1=foo 2=bar
$ test1 $~==spec
zsh: no matches found: fo* ba*
$ test1 $=spec
1=fo* 2=ba*
Is there any order to be maintained while placing functions one another?
I just tried the code on the online compiler provided by purescript.org itself
"http://try.purescript.org"
module Main where
import Prelude
import Data.List
import Data.Array ((..))
import Data.Traversable (traverse)
import Control.Monad.Eff.Console(log)
import TryPureScript(render,withConsole)
main = render =<< withConsole do
log $ "Hello world"
traverse (\x -> log $ show $ x) (1..10)
log $ "Hello world"
The code is compiling absolutely fine when the last log function is removed or when the traverse function is removed.But its not working while they are placed in such an order.These two(log & traverse) functions are working perfectly individually but not together.Help me to get out of this issue.
I think the error message already give you a hint, you can fix by
_ <- traverse (\x -> log $ show $ x) (1..10)
-- or
void $ traverse (\x -> log $ show $ x) (1..10)
Wikipedia provides a link (left side on Print/export) on every article to download the article as pdf. I wrote a small Haskell script which first gets the Wikipedia link and output the rendering link. When I am giving the rendering url as input, I am getting empty tags but the same url in browser provides download link.
Could someone please tell me how to solve this problem? Formated code on ideone.
import Network.HTTP
import Text.HTML.TagSoup
import Data.Maybe
parseHelp :: Tag String -> Maybe String
parseHelp ( TagOpen _ y ) = if any ( \( a , b ) -> b == "Download a PDF version of this wiki page" ) y
then Just $ "http://en.wikipedia.org" ++ snd ( y !! 0 )
else Nothing
parse :: [ Tag String ] -> Maybe String
parse [] = Nothing
parse ( x : xs )
| isTagOpen x = case parseHelp x of
Just s -> Just s
Nothing -> parse xs
| otherwise = parse xs
main = do
x <- getLine
tags_1 <- fmap parseTags $ getResponseBody =<< simpleHTTP ( getRequest x ) --open url
let lst = head . sections ( ~== "<div class=portal id=p-coll-print_export>" ) $ tags_1
url = fromJust . parse $ lst --rendering url
putStrLn url
tags_2 <- fmap parseTags $ getResponseBody =<< simpleHTTP ( getRequest url )
print tags_2
If you try requesting the URL through some external tool like wget, you will see that Wikipedia does not serve up the result page directly. It actually returns a 302 Moved Temporarily redirect.
When entering this URL in a browser, it will be fine, as the browser will follow the redirect automatically. simpleHTTP, however, will not. simpleHTTP is, as the name suggests, rather simple. It does not handle things like cookies, SSL or redirects.
You'll want to use the Network.Browser module instead. It offers much more control over how the requests are done. In particular, the setAllowRedirects function will make it automatically follow redirects.
Here's a quick and dirty function for downloading an URL into a String with support for redirects:
import Network.Browser
grabUrl :: String -> IO String
grabUrl url = fmap (rspBody . snd) . browse $ do
-- Disable logging output
setErrHandler $ const (return ())
setOutHandler $ const (return ())
setAllowRedirects True
request $ getRequest url