I'm trying to learn how to use pipes together with attoparsec by following the tutorial https://hackage.haskell.org/package/pipes-attoparsec-0.1.0.1/docs/Control-Proxy-Attoparsec-Tutorial.html . But I was not able to import Control.Proxy.Trans.Either . In which lib is this module located?
You hit on an old version of pipes-attoparsec corresponding to an old version of pipes. With recent versions, something like the first example would be written without a pipe. We would use the parsed function, which just applies a parser repeatedly until it fails, streaming good parses as they come.
{-# LANGUAGE OverloadedStrings #-}
import Pipes
import qualified Pipes.Prelude as P
import Pipes.Attoparsec
import Data.Attoparsec.Text
import Data.Text (Text)
data Name = Name Text deriving (Show)
hello :: Parser Name
hello = fmap Name $ "Hello " *> takeWhile1 (/='.') <* "."
helloparses :: Monad m => Producer Text m r -> Producer Name m (Either (ParsingError, Producer Text m r) r)
helloparses = parsed hello
process txt = do
e <- runEffect $ helloparses txt >-> P.print
case e of
Left (err,rest) -> print err >> runEffect (rest >-> P.print)
Right () -> return ()
input1, input2 :: Monad m => Producer Text m ()
input1 = each
[ "Hello Kate."
, "Hello Mary.Hello Jef"
, "f."
, "Hel"
, "lo Tom."
]
input2 = input1 >> yield "garbage"
Then we see
-- >>> process input1
-- Name "Kate"
-- Name "Mary"
-- Name "Jeff"
-- Name "Tom"
-- >>> process input2
-- Name "Kate"
-- Name "Mary"
-- Name "Jeff"
-- Name "Tom"
-- ParsingError {peContexts = [], peMessage = "string"}
-- "garbage"
The other principle function pipes-attoparsec defined is just parse. This converts an attoparsec parser into a pipes StateT parser to parse an initial segment of a producer that matches the parser. You can read about them here http://www.haskellforall.com/2014/02/pipes-parse-30-lens-based-parsing.html
Related
Suppose we have this simple API:
type FooAPI
= "foo"
:> QueryParam "age" Int
:> Get '[PlainText] Text
Is there a way to link type-level servant's API with a function that will generate URL for it? Like
someMagicFunction :: Proxy api -> SomeTypeFamily api
someMagicFunction = ?
generateURL :: Maybe Int -> Text
generateURL = someMagicFunction (Proxy #FooAPI)
>>> generateURL (Just 42)
"https://somehost/foo?age=42"
>>> generateURL Nothing
"https://somehost/foo"
I want to increase type-safety of URL generation so if I'll add some new parameter to FooAPI it will immediately appear in the type of generateURL and my code will not compile without editing the calls of generateURL.
I'm aware of servant-client library and I know that client function does somewhat similar but I couldn't figure out how to use this library in my case.
I would say that Servant.Links is exactly what you are looking for.
In particular, in your case I would use allLinks to generate a Link corresponding to the URL piece containing the path and query parameters:
>>> linkURI $ allLinks (Proxy #FooAPI) Nothing
foo
>>> linkURI $ allLinks (Proxy #FooAPI) (Just 18)
foo?age=18
Then I would transform the generated Link into an URI where I would specify required scheme and hostname. Here's a fully working module:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
import Data.Proxy
import Data.Text (Text)
import Network.URI
import Servant.API
import Servant.Links
type FooAPI
= "foo"
:> QueryParam "age" Int
:> Get '[PlainText] Text
generateURL :: Maybe Int -> String
generateURL age = show uri
{ uriScheme = "https:"
, uriAuthority = Just nullURIAuth
{ uriRegName = "somehost" }
, uriPath = "/" <> uriPath uri
}
where
uri = linkURI link
link = allLinks (Proxy #FooAPI) age
And demonstration:
>>> generateURL (Just 42)
"https://somehost/foo?age=42"
>>> generateURL Nothing
"https://somehost/foo"
I'm trying to generate the sentence One of my friends on GF using the GF library.
I failed at finding the right method for constructing a prep after a numeral and on creating the relation of one of with the plural noun.
as the class of Noun Phrase shows, Numeral or Digits only have Common Noun or Noun after them.
CountNP
There is a function for this in the Noun module, but unfortunately it's not in the RGL API. The function is CountNP:
CountNP : Det -> NP -> NP ; -- three of them, some of the boys
To use it in your grammar, you need to open the module NounEng. The usual practice is to open non-API modules qualified: instead of open NounEng in { … }, we give it a shorthand, like N: open (N=NounEng) in { … }. Then in the body of the grammar, you need to write N.CountNP. Here's an example, you can copy and paste it into a file called Friend.gf.
resource Friend = open SyntaxEng, LexiconEng, (N=NounEng) in {
oper
one_Det : Det = mkDet (mkNumeral n1_Unit) ;
my_friends_NP : NP = mkNP (mkDet i_Pron pluralNum) friend_N ;
friend : NP = N.CountNP one_Det my_friends_NP ;
}
Predet
Other times when you want to modify an already existing NP, you can use the Predet category. Here are examples (you can paste them into the same file Friend.gf).
-- The RGL includes some Predets, like all, most and only:
all_friends : NP = mkNP all_Predet my_friends_NP ;
most_friends : NP = mkNP most_Predet my_friends_NP ;
only_friends : NP = mkNP only_Predet my_friends_NP ;
In my Elm program, I'd like to initialize my model based on the query string.
For example, if the query string is ?w=3&h=5 I'd like to have:
initialModel =
{ width = 3
, height = 5
}
Is that possible to achieve this in Elm, or the only way to do this is to get the query parameters in Javascript and pass them via a port?
Elm 0.19
For elm 0.19 the below concept is the same. Both of these packages still exist but have been moved and relabeled as the official elm/url and elm/browser libraries.
Elm 0.18
This example uses evancz/url-parser and elm-lang/navigation. There are a few kinks that aren't straightforward in the documentation, but I've explained them briefly below. The example should speak for itself.
module Main exposing (..)
import Html as H exposing (..)
import Navigation exposing (Location)
import UrlParser as UP exposing ((</>), (<?>), top, parsePath, oneOf, s, stringParam, Parser)
import Maybe.Extra as MaybeExtra exposing (unwrap)
type Route
= UrlRoute (Maybe String) (Maybe String)
| NotFoundRoute
type Msg
= UrlParser Navigation.Location
type alias Model =
{ location : Route
, w : String
, h : String
}
type alias SearchParams =
{ w : Maybe String, h : Maybe String }
main =
Navigation.program UrlParser
{ init = init
, view = view
, update = update
, subscriptions = (\_ -> Sub.none)
}
init : Location -> ( Model, Cmd Msg )
init location =
let
currentPath =
parseLocation location
in
( initialModel currentPath
, Cmd.none
)
parseLocation : Location -> Route
parseLocation location =
case (parsePath matchers location) of
Just route ->
route
Nothing ->
NotFoundRoute
matchers : Parser (Route -> a) a
matchers =
UP.map UrlRoute (UP.s "index" <?> UP.stringParam "w" <?> UP.stringParam "h")
initialModel : Route -> Model
initialModel route =
{ location = route
, w = MaybeExtra.unwrap "" (\x -> Maybe.withDefault "" x.w) (parseParams route)
, h = MaybeExtra.unwrap "" (\x -> Maybe.withDefault "" x.h) (parseParams route)
}
parseParams : Route -> Maybe SearchParams
parseParams route =
case route of
UrlRoute w h ->
Just { w = w, h = h }
NotFoundRoute ->
Nothing
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
UrlParser location ->
( model
, Cmd.none
)
view : Model -> Html msg
view model =
div []
[ h1 [] [ text "URL Info" ]
, div [] [ text ("W is: " ++ model.w) ]
, div [] [ text ("H is: " ++ model.h) ]
]
The "trick" is to create another type alias to place your query params inside of. In the above example I've created the type SearchParams. After creating this type we just use an initialModel that takes in the currentPath.
From there, our model can extract the query params with Maybe.withDefault (it needs to be a Maybe type because the params may not be there). Once we have our data in the model we just print it out in the view.
Hope this helps!
There is no built-in core library way to access the URL. You can use ports and the community library jessitron/elm-param-parsing.
If you also want to set the URL, you can again use ports, or you can use the History API, for which there are bindings in TheSeamau5/elm-history.
Unfortunately jessitron/elm-param-parsing doesn't work with Elm 0.18.
Use elm-lang/navigation package:
http://package.elm-lang.org/packages/elm-lang/navigation/latest/Navigation
https://github.com/elm-lang/navigation/tree/2.1.0
especially this function:
program
: (Location -> msg)
-> { init : Location -> (model, Cmd msg), update : msg -> model -> (model, Cmd msg), view : model -> Html msg, subscriptions : model -> Sub msg }
-> Program Never model msg
In the second parameter you can see "init : Location -> (model, Cmd msg)". This should handle reading of initial URL. To complement that, first parameter is a function which gets called every time URL changes.
(I am aware it's an old question, but this link popped out when I was looking for the solution to the same problem and accepted answer didn't help)
Every time I run "quickCheck prop_xyz", a new random seed is used. How do I enforce QuickCheck to always use the same random seed?
Thanks!
The functionality you need is in Test.QuickCheck; use quickCheckWith to specify custom Args. In particular, there's the replay :: Maybe (StdGen, Int) field, which allows you to replay tests. So you can use the stdArgs defaults and tweak them; for instance,
ghci> :load Main.hs
ghci> import Test.QuickCheck
ghci> import System.Random -- for mkStdGen
ghci> quickCheckWith stdArgs{replay = Just (mkStdGen 42, 0)} prop_xyz
The second component of the tuple has to do with the size of the test cases, but I forget exactly what.
Use the quickCheckWith function
quickCheckWith (stdArgs{replay = Just (myNewGen, testSize)}) property
If you have a test that's failing and you want to reuse it,
result <- quickCheckResult failing_prop
let gen = usedSeed result
let size = usedSize result
to get the size and seed used in a failing test.
Since you also want reproducible errors, a good shrinking algorithm may help. By default it returns [] but provide a nice enough one, then you can end up with the same (minimal) failures even on different random runs.
Example with QuickCheck >= 2.7 and tf-random.
If the output of your failing test run looks something like this:
Failure {
usedSeed = TFGenR 1CE4E8B15F9197B60EE70803C62388671B62D6F88720288F5339F7EC521FEBC4 0 70368744177663 46 0,
USEDSIZE = 75,
...
}
Then you can reproduce the failure as follows:
import Test.QuickCheck.Random (QCGen(..))
import System.Random.TF (TFGen)
qcheck :: Testable a => a -> IO ()
qcheck prop = quickCheckWith args prop
where
usedSeed = QCGen (read "TFGenR 1CE4E8B15F9197B60EE70803C62388671B62D6F88720288F5339F7EC521FEBC4 0 70368744177663 46 0"::TFGen)
usedSize = 75
args = stdArgs{
replay=Just(usedSeed, usedSize)
}
If you want to determine the Generator that caused the failure you could do the following:
import Test.QuickCheck
import System.Random
reproducableTest :: Testable a => a -> Maybe (StdGen, Int) -> IO ()
reproducableTest prop repl = do result <- quickCheckWithResult stdArgs{replay = repl} prop
case result of
Failure{interrupted = False} -> do putStrLn $ "Use " ++ show (usedSeed result) ++ " as the initial seed"
putStrLn $ "Use " ++ show (usedSize result) ++ " as the initial size"
_ -> return ()
Only the first of the two seed numbers should be used as an argument for the function.
So if you have your property prop, your initial call would be reproducableTest prop Nothing. You will get something like
Use x y as the initial seed
Use z as the initial size
Then you would call again with reproducableTest prop $ Just (mkStdGen x , z)
I'm having a surprising amount of difficulty getting the unit tests to run under cabal. I've copied the test code verbatim from the cabal documentation, with the exception of changing the module name
{-# LANGUAGE FlexibleInstances #-}
module Test.Integral ( tests ) where
import Distribution.TestSuite
instance TestOptions (String, Bool) where
name = fst
options = const []
defaultOptions _ = return (Options [])
check _ _ = []
instance PureTestable (String, Bool) where
run (name, result) _ | result == True = Pass
| result == False = Fail (name ++ " failed!")
test :: (String, Bool) -> Test
test = pure
-- In actual usage, the instances 'TestOptions (String, Bool)' and
-- 'PureTestable (String, Bool)', as well as the function 'test', would be
-- provided by the test framework.
tests :: [Test]
tests =
[ test ("bar-1", True)
, test ("bar-2", False)
]
However, when I try to build the tests, I get the following messages:
Test/Integral.hs:6:10:
Not in scope: type constructor or class `TestOptions'
Test/Integral.hs:12:10:
Not in scope: type constructor or class `PureTestable'
I tried importing them directly from Distribution.TestSuite, but it said that they weren't exported. This is simple enough that I have to be doing something stupid, but I can't see what it is.
But for what it's worth, here is some code that works:
module Main (tests) where
import Distribution.TestSuite
tests :: IO [Test]
tests = do
return [
test "foo" Pass
, test "bar" (Fail "It did not work out!")
]
test :: String -> Result -> Test
test name r = Test t
where
t = TestInstance {
run = return (Finished r)
, name = name
, tags = []
, options = []
, setOption = \_ _ -> Right t
}
There is not much support for detailed-0.9 out there. It's possible to hook up existing testing libraries to use it, but even then you will not get progress information as tests pass.
I recommend to use the exitcode-stdio-1.0 interface together with an existing testing framework + use GHCi during development.
A full example for Hspec is here https://github.com/sol/hspec-example.