On fpcomplete.com, I was reading a tutorial on using yesod forms: https://www.fpcomplete.com/school/advanced-haskell/building-a-file-hosting-service-in-yesod/part%202?show=tutorials. Based on the tutorial, my main function is
main = do
titems <- atomically $ newTVar []
liftIO $ warpEnv (Links titems)
What I would like to do is start a Sql database in memory, and then put all the data from the forms in memory. But even a very simple example does not work:
main = runSqlite ":memory:" $ do
-- runMigration migrateAll
-- michaelId <- insert $ Person "Michael" $ Just 26
-- michael <- get michaelId
-- liftIO $ print michael
titems <- atomically $ newTVar []
liftIO $ warpEnv (Links titems)
The error I get is
src/Main.hs#39:13-39:36Couldn't match expected type `SqlPersistT
(Control.Monad.Logger.NoLoggingT
(Control.Monad.Trans.Resource.ResourceT m0))
t0'
with actual type `IO (TVar [a0])'
In a stmt of a 'do' block: titems <- atomically $ newTVar []
In the second argument of `($)', namely
`do { titems <- atomically $ newTVar [];
liftIO $ warpEnv (Links titems) }'
In the expression:
runSqlite ":memory:"
$ do { titems <- atomically $ newTVar [];
liftIO $ warpEnv (Links titems) }
I understand that somehow the types are mismatched, but not sure what function I would have to use in order to fix it. I'd greatly appreciate it if someone could explain to me what is going on.
You need to add liftIO in front of atomically, to lift the IO action into the Persistent monad.
Related
I have hello.ml that has a length function:
let rec length l =
match l with
[] -> 0
| h::t -> 1 + length t ;;
call.ml that uses the function:
#use "hello.ml" ;;
print_int (length [1;2;4;5;6;7]) ;;
In interpreter mode (ocaml), I can use ocaml call.ml to get the results, but when I tried to compile it with ocamlc or ocamlbuild, I got compilation error.
File "call.ml", line 1, characters 0-1:
Error: Syntax error
Then, how to modify the caller, callee, and build command to compile the code into executables?
The #use directive only works in the toplevel (the interpreter). In compiled code you should use the module name: Hello.length.
I'll show how to build the program from a Unix-like command line. You'll have to adapt this to your environment:
$ ocamlc -o call hello.ml call.ml
$ ./call
6
hello.ml
let rec length l =
match l with
[] -> 0
| h::t -> 1 + length t ;;
call.ml
open Hello
let () = print_int (Hello.length [1;2;4;5;6;7]) ;;
Build
ocamlc -o h hello.ml call.ml
or
ocamlbuild call.native
Say I have the following relations :
Section
name Text
UniqueSection name
Subject
name Text
UniqueSubject name
Faculty
name Text
UniqueFaculty name
Assignment
section SectionId
faculty FacultyId
subject SubjectId
UniqueAssignment section subject
Handler:
postNewAssignmentR :: Handler Html
postNewAssignmentR = do
-- don't know what to use instead xxxField for SectionId/FacultyId/SubjectId
sec <- runInputPost $ ireq xxxField "section"
fac <- runInputPost $ ireq xxxField "faculty"
sub <- runInputPost $ ireq xxxField "subject"
runDB $ insert $ Assignment sec fac sub
setMessage "Created new Assignment"
redirect AssignmentsR
If "section", "faculty", and "subject" are dropdowns inputs with their corresponding Ids as values(in Text we get from runInputPost), how to convert them to sectionId, facultyId,..etc ?
or should I go for any other approach to insert foreign keys ?
I just realized you are not generating the forms using Yesod so my original suggestion below may not work. You can probably get the input value as an Int and then use fKey = Key $ PersistInt64 intReturnValue
Unsure if the code below will work for your case:
You can use selectField to get a list of Section Names and then populate it in your dropdown -- the values should map to IDs automatically. I don't use Input Forms but guessing something like this should work:
<*> ireq (selectField sections) "Section Name"
where
sections = do
entities <- runDB $ selectList [] [Asc SectionName]
optionsPairs $ map (\e -> (sectionName $ entityVal e, entityKey e)) entities
So I have a bunch of variables in my workspace. I want to assign a subset of them to a new variable, so I can easily run functions on this subset:
workspace:
...
group10
group40
location40
test
desired assignment:
groupList <- list(group10,group40, ...)
intended regular expression:
^group[0-9]+
Any ideas?
ls accepts a pattern argument:
group10 <- group40 <- location40 <- test <- NA
mysub <- ls(pattern="^group[0-9]+")
mysub
#[1] "group10" "group40"
You can use lapply to loop over the list of variable names and get their values
groupList <- lapply(mysub, get)
or, in one line
groupList <- lapply(ls(pattern="^group[0-9]+"), get)
displayContacts :: Contact ->[String]
displayContacts [] = []
displayContacts (x :xs) = [show (x)] ++ displayContacts (xs)
after performing above function following result showing with exta "\" why is that and how to overcome this
["(\"Fazaal\",\"Naufer\",7712345678)","(\"Tharanga\",\"Chandasekara\",779876543)","
(\"Ruaim\",\"Mohomad\",7798454545)","(\"Yasitha\",\"Lokunarangoda\",7798121212)","
(\"Rochana\",\"Wimalasena\",779878787)","(\"Navin\",\"Dhananshan\",77987345678)","
( \"Akila\",\"Silva\",7798123123)","(\"Sudantha\",\"Gunawardana\",779812456)"]
i want to display this as "Fazaal" "Naufer" 7712345678 likewise
in my function contact is list of tupples :- [("Isuru","Ranaisnghe",123)]
When you show a string, show "hello", the show instance for String adds in quotes, which are escaped when GHCi prints out a data structure.
There are a few solutions, depending on what your goal is. If you just want cleaner output in GHCi then:
putStrLn $ unlines $ displayContacts contact
Writing a unit test in Haskell where an expression should fail when undefined is encountered is a bit tricky. I tried the following with HSpec:
module Main where
import Test.Hspec
import Control.Exception (evaluate)
main :: IO ()
main = hspec $ do
describe "Test" $ do
it "test case" $ do
evaluate (take 1 $ map (+1) [undefined, 2, 3]) `shouldThrow` anyException
to no avail. It reports me did not get expected exception: SomeException
If I evaluate the same expression in REPL, I'd get:
[*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries\base\GHC\Err.hs:79:14 in base:GHC.Err
undefined, called at <interactive>:2:20 in interactive:Ghci1
The problem is that evaluate doesn't force your expression to NH or even WHNF1. Try x <- evaluate (take 1 $ map (+1) [undefined, 2, 3]) in GHCi - it doesn't give you any error! The only reason it does when you paste in evaluate (take 1 $ map (+1) [undefined, 2, 3]) is that GHCi also tries to print the result of what it got and, to do that, it ends up trying to evaluate the expression.
If you want to see how much of a thunk has been evaluated, you can always use :sprint in GHCi:
ghci> x <- evaluate (take 1 $ map (+1) [undefined, 2, 3])
ghci> :sprint x
x = [_]
As you can see, evaluate hasn't forced the expression far enough to realize x contains an undefined. A quick fix is to evaluate the thing you are examining to normal form using force.
import Test.Hspec
import Control.Exception (evaluate)
import Control.DeepSeq (force)
main :: IO ()
main = hspec $ do
describe "Test" $ do
it "test case" $ do
evaluate (force (take 1 $ map (+1) [undefined, 2, 3] :: [Int]))
`shouldThrow` anyException
force lets you trigger the evaluation of thunks until the argument is full evaluated. Note that it has an NFData (stands for "normal form data") constraint on it, so you may find yourself deriving Generic and NFData for your data structures.
1 Thanks for #AlexisKing for pointing out that evaluate does push its argument into WNHF, which is why head $ map (+1) [undefined, 2, 3] does trigger the error. In the case of take, it isn't enough though.