I am new to haskell
I have this program:
loop height weight=do
line<-getLine
if line=="1" then
do
height<-getLine
loop height weight
else if line=="2" then
do
weight<-getLine
loop height weight
else if line=="3" then
do
putStrLn (height)
else
do
putStrLn "error"
main :: IO ()
main = do
loop "" ""
It works fine,now I change it as this:
data A=A {height::String,weight::String}
loop::A->IO ()
loop z=do
line<-getLine
if line=="1" then
do
height<-getLine
let z.height=height
loop z
else if line=="2" then
do
weight<-getLine
let z.weight=weight
loop z
else if line=="3" then
do
putStrLn ((height z)++(weight z))
else
do
putStrLn "error"
main :: IO ()
main = do
let z=A "" ""
loop z
this program is wrong
I know in haskell and other function program there is no assignment,so let z.height=height is wrong,but I don't know how to write it right.I need some help,thanks!
You can use the record update notation:
if line=="1" then
do
height'<-getLine
loop z{height = height'}
Basically, z{height = height'} is a new record value, having the same fields as z except for the updated one. In this case, it is equivalent to A height' (weight z).
Related
I'm trying to make the folowing function:
repcountIORIban :: IORef -> Int -> Int -> Int -> Int -> Lock -> IORef -> Lock -> Int -> Int -> IO ()
repcountIORIban count number lower modulus amountthreads lock done lock2 difference rest = do
if rest > number
then let extra = 1
else let extra = 0
if number + 1 < amountthreads
then
forkIO $ realcountIORIban(count lower (lower + difference + extra - 1) modulus lock done lock2)
repcountIORIban (count (number + 1) (lower + difference + extra) modulus amountthreads lock done lock2 difference rest)
else
forkIO $ realcountIORIban(count lower (lower + difference + extra - 1) modulus lock done lock2)
But I can't run the program from which this function is a part of. It gives me the error:
error: parse error on input `else'
|
113 | else let extra = 0
| ^^^^
I've got this error a lot of times withing my program but I don't know what I'm doing wrong.
This is incorrect, you can't let after then/else and expect those lets to define bindings which are visible below.
do if rest > number
then let extra = 1 -- wrong, needs a "do", or should be "let .. in .."
else let extra = 0
... -- In any case, extra is not visible here
Try this instead
do let extra = if rest > number
then 1
else 0
...
Further, you need then do if after that you need to perform two or more actions.
if number + 1 < amountthreads
then do
something
somethingElse
else -- use do here if you have two or more actions
...
we were hoping to use threads to get things going faster in an algorithm with many loops whose results are not interdependent.
within the code we hoped to port to rcpp, there is a call to model.matrix.
This did not appear straightforward to port.
Investigating this further (as to what code this runs for our use case), revealed that the S3 method for lm objects does some preparatory work on the variable and then calls the default version of the function as can be seen in this copy-paste of the code:
function (object, ...)
{
if (n_match <- match("x", names(object), 0L))
object[[n_match]]
else {
data <- model.frame(object, xlev = object$xlevels, ...)
if (exists(".GenericCallEnv", inherits = FALSE))
NextMethod("model.matrix", data = data, contrasts.arg = object$contrasts)
else {
dots <- list(...)
dots$data <- dots$contrasts.arg <- NULL
do.call("model.matrix.default", c(list(object = object,
data = data, contrasts.arg = object$contrasts),
dots))
}
}
}
the default version of the function farms at least some of its functionality out to a compiled C function:
function (object, data = environment(object), contrasts.arg = NULL,
xlev = NULL, ...) {
t <- if (missing(data))
terms(object)
else terms(object, data = data)
if (is.null(attr(data, "terms")))
data <- model.frame(object, data, xlev = xlev)
else {
reorder <- match(vapply(attr(t, "variables"), deparse2,
"")[-1L], names(data))
if (anyNA(reorder))
stop("model frame and formula mismatch in model.matrix()")
if (!identical(reorder, seq_len(ncol(data))))
data <- data[, reorder, drop = FALSE]
}
int <- attr(t, "response")
if (length(data)) {
contr.funs <- as.character(getOption("contrasts"))
namD <- names(data)
for (i in namD) if (is.character(data[[i]]))
data[[i]] <- factor(data[[i]])
isF <- vapply(data, function(x) is.factor(x) || is.logical(x),
NA)
isF[int] <- FALSE
isOF <- vapply(data, is.ordered, NA)
for (nn in namD[isF]) if (is.null(attr(data[[nn]], "contrasts")))
contrasts(data[[nn]]) <- contr.funs[1 + isOF[nn]]
if (!is.null(contrasts.arg)) {
if (!is.list(contrasts.arg))
warning("non-list contrasts argument ignored")
else {
if (is.null(namC <- names(contrasts.arg)))
stop("'contrasts.arg' argument must be named")
for (nn in namC) {
if (is.na(ni <- match(nn, namD)))
warning(gettextf("variable '%s' is absent, its contrast will be ignored",
nn), domain = NA)
else {
ca <- contrasts.arg[[nn]]
if (is.matrix(ca))
contrasts(data[[ni]], ncol(ca)) <- ca
else contrasts(data[[ni]]) <- contrasts.arg[[nn]]
}
}
}
}
}
else {
isF <- FALSE
data[["x"]] <- raw(nrow(data))
}
ans <- .External2(C_modelmatrix, t, data)
if (any(isF))
attr(ans, "contrasts") <- lapply(data[isF], attr,
"contrasts")
ans
}
is there some way of calling C_modelmatrix from Rcpp at all, whether it is single OR multi-threaded? Is there any library or package that does essentially the same thing from within Rcpp so I don't have to reinvent the wheel here? I'd rather not have to fully re-implement everything that model.matrix does if I can avoid it.
as we don't actually have functioning code, there isn't any to show for this yet.
The relevant portion of the function we were trying to speed up calls model.matrix like this: ("model.y is an lm", data are both copies of an original object returned by model.frame(model.y) )
ymat.t <- model.matrix(terms(model.y), data=pred.data.t)
ymat.c <- model.matrix(terms(model.y), data=pred.data.c)
this isn't really a results based question, more of an approach/methods based question
You can call model.matrix from within C++, but you cannot do so in a multi-threaded way.
There will also be overhead, but if the function call is needed deep within the middle of your code, it could be worth it as a convenience.
Example:
// [[Rcpp::export]]
RObject call(RObject x, RObject y){
Environment env = Environment::global_env();
Function f = env["model.matrix"];
RObject res = f(x,y);
return res;
}
I want to move an object in Haskell Gloss every frame a key is pressed, not just the one frame that the key is started being pressed. (Example: While 'w' key is pressed, accelerate object every frame)
Edit: I tried using the second parameter of EventKey but to no avail.
My code:
--TODO - Holding keys doesn't work yet
handleKeys :: Event -> AsteroidsGame -> AsteroidsGame
handleKeys (EventKey (Char char) _ _ _) game
| char == 'w' = move 0 1
| char == 'a' = move (-1) 0
| char == 's' = move 0 (-1)
| char == 'd' = move 1 0
where move x y = game {player = accelerateObject (player game) x y}
handleKeys _ game = game
accelerateObject :: Object -> Float -> Float -> Object
accelerateObject obj hor ver = obj {vel = (vx + hor, vy + ver)}
where (vx, vy) = vel obj
As OP correctly deduced, gloss gives you input events ("key was just pressed", "mouse was just moved"), rather than input state ("key is currently pressed", "mouse is at x,y"). There doesn't seem to be a built-in way to see input state on each frame, so we'll have to make our own workaround. Thankfully, this isn't too difficult!
For a simple working example, we'll make an incredibly fun "game" where you can watch a counter count upwards while the space bar is pressed. Riveting. This approach generalises to handling any key presses, so it'll be easy to extend to your case.
The first thing we need is our game state:
import qualified Data.Set as S
data World = World
{ keys :: S.Set Key
, counter :: Int }
We keep track of our specific game state (in this case just a counter), as well as state for our workaround (a set of pressed keys).
Handling input events just involves either adding a key to our set of currently pressed keys or removing it:
handleInput :: Event -> World -> World
handleInput (EventKey k Down _ _) world = world { keys = S.insert k (keys world)}
handleInput (EventKey k Up _ _) world = world { keys = S.delete k (keys world)}
handleInput _ world = world -- Ignore non-keypresses for simplicity
This can easily be extended to handle eg. mouse movement, by changing our World type to keep track of the last known coordinates of the cursor, and setting it in this function whenever we see an EventMotion event.
Our frame-to-frame world update function then uses the input state to update the specific game state:
update :: Float -> World -> World
update _ world
| S.member (SpecialKey KeySpace) (keys world) = world { counter = 1 + counter world }
| otherwise = world { counter = 0 }
If the spacebar is currently pressed (S.member (SpecialKey KeySpace) (keys world)), increment the counter - otherwise, reset it to 0. We don't care about how much time as elapsed between frames so we ignore the float argument.
Finally we can render our game and play it:
render :: World -> Picture
render = color white . text . show . counter
main :: IO ()
main = play display black 30 initWorld render handleInput update
where
display = InWindow "test" (800, 600) (0, 0)
initWorld = World S.empty 0
I'm trying to use the value of a textarea with js_of_ocaml. Here is my source code :
let matrix () =
let text1 = get_textarea "input_1" in
let btn1 = get_elem "btn_1" in
text1##placeholder <- Js.string "Write your matrix !";
btn1##textContent <- Js.some (Js.string "Calculate");
btn1##onclick <- Dom_html.handler (if Matrix.is_matrix (Js.to_string text1##value)
then (let matrix = Matrix.get_matrix (Js.to_string text1##value) in
fun ev -> (set_matrix_caracteristics (Matrix.nb_lines matrix) (Matrix.nb_columns matrix) (Matrix.determinant matrix) ; Js._false))
else fun ev -> (error_input_matrix() ; Js._false))
I want to do some calculs on a matrix, and the matrix is write by the user through a textarea with an html interface.
I think the problem is that the value of text1don't change, even if I write something in the textarea. Whatever the input on the textarea is, the result is the same.
Do anyone know how to use the value write by the user ?
Thanks !
Your probleme here is that you evaluate text1##value before defining the handler function, so the value is evaluated when the handler is installed, and then never changed. the following should works
btn1##onclick <- Dom_html.handler (
fun ev ->
if Matrix.is_matrix (Js.to_string text1##value)
then let matrix = Matrix.get_matrix (Js.to_string text1##value) in
(set_matrix_caracteristics (Matrix.nb_lines matrix) (Matrix.nb_columns matrix) (Matrix.determinant matrix) ; Js._false)
else error_input_matrix() ; Js._false
)
Here's the SQLite3 Haskell bindings with the ability to create function: http://hackage.haskell.org/packages/archive/sqlite/0.5.1/doc/html/Database-SQLite.html
But I can't get to use this feature, I wrote the code like this:
increment a = a + 1
checkout = do
handle <- openConnection "test.db"
ok <- createFunction handle "woot" (IsFunctionHandler increment)
return $ execStatement handle "SELECT woot(5)";
But it isn't compile with "Not in scope: data constructor `IsFunctionHandler'" error
The correct code is:
module Test where
import Database.SQLite
import Int
increment :: Int64 -> Int64
increment a = a + 1
checkout :: IO (Either String [[Row Value]])
checkout = do
handle <- openConnection "test.db"
ok <- createFunction handle "woot" increment
execStatement handle "SELECT woot(5), woot(7), woot(128)"
Thanks to HaskellElephant
IsFunctionHandler is a class, not a data constructor. It has several instances so if increment is an instance of IsFunctionHandler, wich it in this case is, you should be able to write:
createFunction handle "woot" increment