Extracting the year from a timestamp field inside an Esqueleto query - sql

I am trying to make use of the unsafeSqlExtractSubField from Esqueleto to create one that will extract the year from a date, such as:
data ReportRow = ReportRow Text
userSignupData :: MonadIO m => Key User -> SqlPersistT m [ReportRow]
userSignupData _ = fmap toRow <$> select (from query)
where
query s =
pure $ (extractYear $ s ^. UserCreatedAt)
toRow yearVal = ReportRow (showText . unValue $ yearVal)
extractYear :: UnsafeSqlFunctionArgument a => a -> SqlExpr (Value Integer)
extractYear =
unsafeSqlExtractSubField "year"
showText :: Show a => a -> Text
showText = T.pack . show
But I am getting the error:
Could not deduce
(UnsafeSqlFunctionArgument
(expr0 (Value UTCTime)))
arising from a use of ‘query’
from the context: MonadIO m
bound by the type signature for:
userSignupData :: forall (m :: * -> *).
MonadIO m =>
Key User -> SqlPersistT m [ReportRow]
The type variable ‘expr0’ is ambiguous
|
20 | userSignupData _ = fmap toRow <$> select (from query)
| ^^^^^
Do I need to define an instance of UnsafeSqlFunctionArgument for UTCTime here or am I trying to fit a square peg into a round hole ?
I'm not after answers that state that I could extract the date at the haskell level, I'd like to get the year inside the query so that I can perform an SQL GROUP BY inside the query.

Related

How do I solve this ambiguous type variable error in Haskell?

I couldn't find an answer to my question among several ambiguous type variable error questions.
I'm currently trying to get this code I found to work. (https://gist.github.com/kirelagin/3886243)
My code:
import Control.Arrow
import Data.List
import qualified Data.Map as M
import Data.Function
main = do
putStrLn "Start test"
let foo = "Hello World"
let freqTest = freqList foo
putStrLn "Frequentie list"
print freqTest
putStrLn "Done.."
let treeTest = buildTree freqTest
putStrLn "Huffman Tree"
print treeTest
putStrLn "Done.."
let codeMaphTest = buildCodemap treeTest
putStrLn "Codemap ding"
-- print codeMaphTest
putStrLn "Done.."
--This typeclass is supposed to make life _a bit_ easier.
class Eq a => Bits a where
zer :: a
one :: a
instance Bits Int where
zer = 0
one = 1
instance Bits Bool where
zer = False
one = True
-- Codemap is generated from a Huffman tree. It is used for fast encoding.
type Codemap a = M.Map Char [a]
-- Huffman tree is a simple binary tree. Each leaf contains a Char and its weight.
-- Fork (node with children) also has weight = sum of weights of its children.
data HTree = Leaf Char Int
| Fork HTree HTree Int
deriving (Show)
weight :: HTree -> Int
weight (Leaf _ w) = w
weight (Fork _ _ w) = w
-- The only useful operation on Huffman trees is merging, that is we take
-- two trees and make them children of a new Fork-node.
merge t1 t2 = Fork t1 t2 (weight t1 + weight t2)
-- `freqList` is an utility function. It takes a string and produces a list
-- of pairs (character, number of occurences of this character in the string).
freqList :: String -> [(Char, Int)]
freqList = M.toList . M.fromListWith (+) . map (flip (,) 1)
-- `buildTree` builds a Huffman tree from a list of character frequencies
-- (obtained, for example, from `freqList` or elsewhere).
-- It sorts the list in ascending order by frequency, turns each (char, freq) pair
-- into a one-leaf tree and keeps merging two trees with the smallest frequencies
-- until only one tree is remaining.
buildTree :: [(Char, Int)] -> HTree
buildTree = bld . map (uncurry Leaf) . sortBy (compare `on` snd)
where bld (t:[]) = t
bld (a:b:cs) = bld $ insertBy (compare `on` weight) (merge a b) cs
-- The next function traverses a Huffman tree to obtain a list of codes for
-- all characters and converts this list into a `Map`.
buildCodemap :: Bits a => HTree -> Codemap a
buildCodemap = M.fromList . buildCodelist
where buildCodelist (Leaf c w) = [(c, [])]
buildCodelist (Fork l r w) = map (addBit zer) (buildCodelist l) ++ map (addBit one) (buildCodelist r)
where addBit b = second (b :)
-- Simple functions to get a Huffman tree or a `Codemap` from a `String`.
stringTree :: String -> HTree
stringTree = buildTree . freqList
stringCodemap :: Bits a => String -> Codemap a
stringCodemap = buildCodemap . stringTree
-- Time to do the real encoding and decoding!
-- Encoding function just represents each character of a string by corresponding
-- sequence of `Bit`s.
encode :: Bits a => Codemap a -> String -> [a]
encode m = concat . map (m M.!)
encode' :: Bits a => HTree -> String -> [a]
encode' t = encode $ buildCodemap t
-- Decoding is a little trickier. We have to traverse the tree until
-- we reach a leaf which means we've just finished reading a sequence
-- of `Bit`s corresponding to a single character.
-- We keep doing this to process the whole list of `Bit`s.
decode :: Bits a => HTree -> [a] -> String
decode tree = dcd tree
where dcd (Leaf c _) [] = [c]
dcd (Leaf c _) bs = c : dcd tree bs
dcd (Fork l r _) (b:bs) = dcd (if b == zer then l else r) bs
Output:
huffmancompress.hs:17:24: error:
* Ambiguous type variable `a0' arising from a use of `buildCodemap'
prevents the constraint `(Bits a0)' from being solved.
Relevant bindings include
codeMaphTest :: Codemap a0 (bound at huffmancompress.hs:17:9)
Probable fix: use a type annotation to specify what `a0' should be.
These potential instances exist:
instance Bits Bool -- Defined at huffmancompress.hs:35:10
instance Bits Int -- Defined at huffmancompress.hs:31:10
* In the expression: buildCodemap treeTest
In an equation for `codeMaphTest':
codeMaphTest = buildCodemap treeTest
In the expression:
do putStrLn "Start test"
let foo = "Hello World"
let freqTest = freqList foo
putStrLn "Frequentie list"
....
|
17 | let codeMaphTest = buildCodemap treeTest
| ^^^^^^^^^^^^^^^^^^^^^
I've tried serveral things I found on the internet but nothing worth mentioning to be honest.
Maybe any of you guys can help me out!
On line 17, where the error points you:
let codeMaphTest = buildCodemap treeTest
What type is codeMaphTest? Should it be Codemap Int? Or Codemap String? Or, perhaps, Codemap Bool? The function buildCodemap can return any type, as long as it has an instance of Bit. So what type should it be?
The compiler doesn't know. There is nowhere to glean this information from. It's ambiguous.
And this is exactly what the compiler is telling you: "ambiguous type variable".
One way to fix this is to provide a type annotation (exactly as the error message says, by the way):
let codeMaphTest :: Codemap Int = buildCodemap treeTest
Note that I chose Int just as an example, because I don't know which type you meant (I'm somewhat like the compiler in that respect). Please substitute your own type - the one you actually wanted there.
Your code is indeed ambiguous. buildCodemap treeTest has a polymorphic type Bits a => Codemap a, so it can be used as a Codemap Int, a Codemap Bool, or even as another type if you defines further instances of Bits.
This is not a problem, on its own, but later on you try to use this value (e.g., to print it), so we really need to pick a concrete type a.
You could pick a at the definition point:
let codeMaphTest :: Codemap Int
codeMaphTest = buildCodemap treeTest
Or, alternatively, you could choose a later on, where you use it
print (codeMaphTest :: Codemap Int)

Elm: How can I find out the type of an Elm expression or a subexpression in elm-repl?

How can I find out the type of an Elm expression or a subexpression in elm-repl ?
Haskell's :type or :t equivalent in Elm REPL?
The Elm REPL automatically prints the type of whatever you enter. For example:
> "foo"
"foo" : String
> f = \a b c -> (a + 1, b ++ "!", c || False)
<function> : number -> String -> Bool -> ( number, String, Bool )
> f
<function> : number -> String -> Bool -> ( number, String, Bool )
> f2 a b c = (a + 1, b ++ "!", c || False)
<function> : number -> String -> Bool -> ( number, String, Bool )
As #amalloy points out, without an equivalent to GHCi's :type command, Elm REPL (as of 0.18) forces evaluation of an expression prior to showing you the type, which may be undesirable for expensive function calls. In its current version, there is no way around this.

How can I quickly select an option from a dropdown using Haskell and webdriver?

I have a site with a <select> that has more than 100 <option>s in it, one for every country in the world. My test needs to select one. My current solution - below - takes around 2.5 seconds. I'd like it to be much faster.
findChildrenByLabel :: (WD.WebDriver m, MonadIO m) =>
Text -> Text -> m [WD.Element]
findChildrenByLabel label tagName = do
parentEl <- findFieldByLabel label
WD.findElemsFrom parentEl $ WD.ByTag tagName
findChildByLabelF :: (WD.WebDriver m, MonadIO m) =>
Text -> Text -> (WD.Element -> m Bool) -> m WD.Element
findChildByLabelF label tagName f = do
children <- findChildrenByLabel label tagName
child <- filterM f children
liftIO $ child `shouldSatisfy` ((==1) . length)
return (headEx child)
selectDropdownByLabel :: (WD.WebDriver m, MonadIO m) => Text -> Text -> m ()
selectDropdownByLabel label optionName = do
targetOption <- findChildByLabelF
label "option" (\el -> (== optionName) <$> WD.getText el)
WD.click targetOption
I found this SO answer in Java, but there doesn't seem to be anything like Selenium.Support or SelectByText for Haskell.
Based on danidiaz's answer, I wrote this:
findFieldByLabel :: (WD.WebDriver m, MonadIO m) => Text -> m WD.Element
findFieldByLabel str = do
labels :: [WD.Element] <- WD.findElems $ WD.ByXPath $
"//label[text() = \"" <> str <> "\"]"
els <- catMaybes <$> mapM (`WD.attr` "for") labels
liftIO $ els `shouldSatisfy` ((==1) . length)
WD.findElem $ WD.ById $ headEx els
selectDropdownByLabel :: (WD.WebDriver m, MonadIO m) => Text -> Text -> m ()
selectDropdownByLabel label optionName = do
field <- findFieldByLabel label
targetOptions <- WD.findElemsFrom field $ WD.ByXPath $
"option[text() = \"" <> optionName <> "\"]"
liftIO $ targetOptions `shouldSatisfy` ((==1) . length)
WD.click $ headEx targetOptions
I use it like this:
selectDropdownByLabel "Country of residence" "United States"
The original solution took around 2.5 seconds, this is around 0.16. Big improvement, thanks danidiaz!

How should I model a type-safe index in Purescript?

In my application, I'd like to index sets of objects in a type-safe way using a structure similar to a relational database index. For example, I might want to index a set of User objects based on age and name:
import Data.Map as M
import Data.Set as S
type AgeNameIndex = M.Map Int (M.Map String (S.Set User))
Furthermore, I'd like to do operations like union and difference on indexes efficiently, e.g.:
let a = M.singleton 42 $ M.singleton "Bob" $ S.singleton $ User { ... }
b = M.singleton 42 $ M.singleton "Tim" $ S.singleton $ User { ... }
c = union a b -- contains both Bob and Tim
I've tried to model this as follows:
module Concelo.Index
( index
, union
, subtract
, lastValue
, subIndex ) where
import Prelude (($), (>>>), flip, Unit, unit, class Ord)
import Control.Monad ((>>=))
import Data.Map as M
import Data.Set as S
import Data.Maybe (Maybe(Nothing, Just), fromMaybe)
import Data.Tuple (Tuple(Tuple))
import Data.Foldable (foldl)
import Data.Monoid (mempty)
class Index index key value subindex where
isEmpty :: index -> Boolean
union :: index -> index -> index
subtract :: index -> index -> index
lastValue :: index -> Maybe value
subIndex :: key -> index -> subindex
instance mapIndex :: (Index subindex subkey value subsubindex) =>
Index (M.Map key subindex) key value subindex where
isEmpty = M.isEmpty
union small large =
foldl (m (Tuple k v) -> M.alter (combine v) k m) large (M.toList small)
where
combine v = case _ of
Just v' -> Just $ union v v'
Nothing -> Just v
subtract small large =
foldl (m (Tuple k v) -> M.alter (minus v) k m) large (M.toList small)
where
minus v = (_ >>= v' ->
let subindex = subtract v v' in
if isEmpty subindex then Nothing else Just subindex)
lastValue m = M.findMax m >>= (_.value >>> lastValue)
subIndex k m = fromMaybe mempty $ M.lookup k m
instance setIndex :: (Ord value) => Index (S.Set value) Unit value Unit where
isEmpty = S.isEmpty
union = S.union
subtract = flip S.difference
lastValue s = Nothing -- todo: S.findMax
subIndex _ _ = unit
index f = foldl (acc v -> union (f v) acc) mempty
However, the Purescript compiler doesn't like that:
Compiling Concelo.Index
Error found:
in module Concelo.Index
at /home/dicej/p/pssync/src/Concelo/Index.purs line 24, column 1 - line 44, column 49
No type class instance was found for
Concelo.Index.Index subindex0
t1
t2
t3
The instance head contains unknown type variables. Consider adding a type annotation.
in value declaration mapIndex
where subindex0 is a rigid type variable
t1 is an unknown type
t2 is an unknown type
t3 is an unknown type
See https://github.com/purescript/purescript/wiki/Error-Code-NoInstanceFound for more information,
or to contribute content related to this error.
My understanding of this message is that I haven't properly stated that map values in the mapIndex instance are themselves Index instances, but I don't know how to fix that. Where might I add a type annotation to make this compile? Or am I even on the right track given what I'm trying to do?
This is almost certainly because PureScript currently lacks functional dependencies (or type families) which makes this kind of information un-inferrable. There's a writeup of the issue here: https://github.com/purescript/purescript/issues/1580 - it is something we want to support.
There was a discussion about a case very similar to this today as it happens: https://github.com/purescript/purescript/issues/2235
Essentially, the problem here is that the functions of the class do not use all of the type variables, which means there's no way to propagate the information to the constraint for looking up a suitable instance.
I don't really have a suggestion for how to do what you're after here with things as they are, aside from avoiding the class and implementing it with specific types in mind.

GHC rejects ST monad code as unable to unify type variables?

I wrote the following function:
(.>=.) :: Num a => STRef s a -> a -> Bool
r .>=. x = runST $ do
v <- readSTRef r
return $ v >= x
but when I tried to compile I got the following error:
Could not deduce (s ~ s1)
from the context (Num a)
bound by the type signature for
.>=. :: Num a => STRef s a -> a -> Bool
at test.hs:(27,1)-(29,16)
`s' is a rigid type variable bound by
the type signature for .>=. :: Num a => STRef s a -> a -> Bool
at test.hs:27:1
`s1' is a rigid type variable bound by
a type expected by the context: ST s1 Bool at test.hs:27:12
Expected type: STRef s1 a
Actual type: STRef s a
In the first argument of `readSTRef', namely `r'
In a stmt of a 'do' expression: v <- readSTRef r
Can anyone help?
This is exactly as intended. An STRef is only valid in one run of runST. And you try to put an external STRef into a new run of runST. That is not valid. That would allow arbitrary side-effects in pure code.
So, what you try is impossible to achieve. By design!
You need to stay within the ST context:
(.>=.) :: Ord a => STRef s a -> a -> ST s Bool
r .>=. x = do
v <- readSTRef r
return $ v >= x
(And as hammar points out, to use >= you need the Ord typeclass, which Num doesn't provide.)