I'm new to Snap and Haskell. I am attempting to turn this output:
[("LDPNLNDQQFHUKIWZII",2191.12),("NLNDQQFHUKIWZIIXDC",2195.0696),("NZRAIEUALDPNLNDQQFH",2192.0503)]
into JSON. So I know the type is [(String, Double)], but that doesn't help me with the error message arising from GHCi when entering writeJSON [("LDPNLNDQQFHUKIWZII",2191.12),("NLNDQQFHUKIWZIIXDC",2195.0696),("NZRAIEUALDPNLNDQQFH",2192.0503)]
:
No instance for (MonadSnap m0) arising from a use of `writeJSON'
The type variable `m0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance MonadSnap m =>
MonadSnap (Control.Monad.Trans.Cont.ContT c m)
-- Defined in `snap-core-0.9.5.0:Snap.Internal.Instances'
instance (MonadSnap m, Control.Monad.Trans.Error.Error e) =>
MonadSnap (Control.Monad.Trans.Error.ErrorT e m)
-- Defined in `snap-core-0.9.5.0:Snap.Internal.Instances'
instance MonadSnap m =>
MonadSnap (Control.Monad.Trans.List.ListT m)
-- Defined in `snap-core-0.9.5.0:Snap.Internal.Instances'
...plus 8 others
In the expression: writeJSON x
In an equation for `it': it = writeJSON x
I'm not married to the current data structure (I just created it to clump an amino acid sequence with its mass). Ideally I would get JSON data that looks like this:
{ "LDPNLNDQQFHUKIWZII":2191.12, "NLNDQQFHUKIWZIIXDC":2195.0696, "NZRAIEUALDPNLNDQQFH":2192.0503 }
The output, [("LDPNLNDQQFHUKIWZII",2191.12),("NLNDQQFHUKIWZIIXDC",2195.0696),("NZRAIEUALDPNLNDQQFH",2192.0503)]
, is calculated by a function that takes two pieces of input from the user: an original peptide sequence, and a weight (the program finds fragments from the peptide sequence that equal the entered weight).
Any help/direction is appreciated. Thanks!
I generated the app using snap init barebones
. Here is what the handler looks like. I am getting the error at the writeJSON result
line. I am intending on using the getParam lines, but to start I was just trying to get the JSON response.
possibleMatches :: Snap ()
possibleMatches = do
peptideSequence <- getParam "peptide_sequence"
weight <- getParam "weight"
let sequence = "V(3D)NK(3F)NKEXCNZRAIEUALDPNLNDQQFHUKIWZIIXDC"
let weight = 2194.9
let results = calculationResults weight sequence
let result = take 1 [ seq | (seq,wt) <- results ]
maybe (writeBS "must specify params in URL")
writeJSON result
The error from the compiler is:
Couldn't match expected type `Maybe a0'
with actual type `[([Char], Float)]'
So I need to figure out how to deal with Maybe. I'm reading on it but some help would be appreciated.
writeJSON
has the type
writeJSON :: (MonadSnap m, ToJSON a) => a -> m ()
where the a
and the m
must be resolved to specific types before the compiler can run the code. You can certainly use your object of type [(String, Double)]
as the input because String
has an instance of ToJSON
, as does Double
, as do any pair of things with ToJSON
instances (i.e. instance (ToJSON a, ToJSON b) => ToJSON (a, b)
), and finally as do lists of things with ToJSON
instances (i.e. instance ToJSON v => ToJSON [a]
).
So the problem is entirely in trying to determine what m
is. The compiler is complaining that as long as m
is "anything" it cannot be sure that it's an instance of MonadSnap
. We can reassure the type checker at least by just asserting it is so
>>> :t writeJSON [("foo", 3)] :: MonadSnap m => m ()
writeJSON [("foo", 3.0)] :: MonadSnap m => m ()
But we need to pick a concrete choice of m
before we can run it. If you have a test application which uses MonadSnap
then you can embed this line of code there, for instance.
For testing, however, you probably should just use the function that writeJSON
depends upon: encode
from Data.Aeson
.
>>> encode [("foo", 3.0)]
"[[\"foo\",3.0]]"