Error: “Error: Channel ID must be specified“ when using Braintree
I was getting this error. I had my dropin code wrapped in an on-load event handler embedded in an HTML template just below the script tag that includes the Braintree javascript library.
Someone on lobste.rs asked about printf debugging in Haskell
Someone else pointed out Debug.Trace without giving any explanation, and another person asked for clarification, so here’s my attempt!
Hackage docs tell me trace has the type String -> a -> a. That means, if I give trace a String and Something Else, it’ll give me Something Else back. So, you can stick trace + some string in your Haskell functions without changing the type of the function – that’s what makes it handier than print.
I just made this program:
data Cat = Cat { lives :: Int } deriving (Show) curiosity :: Cat -> Cat curiosity cat = cat { lives = lives cat + 1 } main = do let cat = curiosity (Cat 9) print cat
If you run this, you’ll get a cat with ten lives! Something in my program has gone horribly wrong!
Here’s how I can debug it with trace:
import Debug.Trace (trace) data Cat = Cat { lives :: Int } deriving (Show) curiosity :: Cat -> Cat curiosity cat = trace ("My cat has " ++ show (lives cat) ++ " lives") $ cat { lives = lives cat + 1 } main = do let cat' = curiosity (Cat 9) print cat'
Now I can see the following output:
My cat has 10 lives Cat {lives = 10}
I can even alter the program to:
curiosity cat = let newCat = cat { lives = lives cat + 1 } in trace ("My cat had " ++ show (lives cat) ++ " lives but now it has " ++ show (lives newCat) ++ " lives") newCat
And get the even more helpful:
My cat had 9 lives but now it has 10 lives Cat {lives = 10}
Woah, my curiousity function is doing the exact opposite of what was intended! Good to know! Thanks, trace!
Most of the projects we’re working on right now are Rails, but even in some of those we use Haskell! We use Shake scripts to automate builds.
We also have a couple clients with websites that run on Haskell. Both are running our magazine subscription platform, Wayland. Wayland was originally written for Jacobin Magazine. Wayland uses a lot of really cool Haskell libraries, including:
Snap web framework
Opaleye (typesafe and composable SQL)
Digestive functors (great library for form validation -- terrible name)
We also took part of Wayland and pulled it out into it’s own library and made it open source: Offset. Offset allows you to write Heist templates that incorporate WordPress content, using the WordPress REST API and Redis. It is super cool and I hope to write a longer post about it sometime!
Using Haskell for web has it’s up and downs.
Things that are not so fun:
1) Lack of friendly, “getting started“-style documentation. Hackage is great (most of the time...), but sometimes you just want a tutorial!
2) Some libraries are not so great, but they’re the only ones we’ve got... :/
3) Single-letter variable names and “ticks” (i.e., `x` and `x’`). I resisted for a long time, but by now these have infected my Haskell writing as well. Sometimes it even creeps into my Ruby! ;_;
4) Not being able to get useful solutions by Googling error messages because not as many people use Haskell as other languages (especially not the way we use Haskell).
Things that are super fun:
1) So easy to make big sweeping changes. We recently decided to use our framework Fn for Wayland instead of Snap. I rewrote hspec-snap to create hspec-fn (basically search-and-replace style) and it was fairly painless. The compiler guided me through most of the changes I needed to make!
2) Speaking of the compiler -- I am a super lazy programmer. I don’t want to go hunting for bugs! Luckily, GHC catches most of them for me, and sometime the error messages are even helpful. :D
3) Warp and WAI are really cool.
4) I love testing with hspec.
5) I love thinking about web apps as simply a side-effecting function from Request to Response!
There are other things too, but that’s just off the top of my head!
Sometimes (often 😞) a docker container on Beanstalk is doing the wrong thing and you don’t know why! It’s working fine on your machine! How do you connect to that container while it’s running?
First, ssh into a beanstalk instance with eb ssh.
Then list all the docker containers:
$ sudo docker ps CONTAINER ID ... NAME a887a3471044 ... ecs-awseb-position-staging-stuff-dkjr34dfjs 5e43b2a17a6c ... ecs-awseb-position-staging-blah-dkjr34dfjs 4c01a1abfff9 ... ecs-awseb-position-staging-whatever-dkjr34dfjs
You’ll see a bunch of containers, all with very unhelpfully long names. Luckily you can use even just the first few characters of the container id instead.
Now if we want to take a peek instead our “stuff” containter, we can run sudo docker exec -it a88 /bin/bash. That starts a shell process in the stuff container. We can look around at files and logs and check out environment variables or run rails c for our Rails apps.
Fn is pretty unique among Haskell frameworks in how it handles application state.
To use Fn, you create a "context" data type with a field for the FnRequest. You make your context an instance of RequestContext by defining how to access and modify that field.
Here's an example Context from a real (simple) production project:
data Ctxt = Ctxt { _req :: FnRequest , _db :: Pool PG.Connection , _heist :: FnHeistState Ctxt } makeLenses ''Ctxt instance RequestContext Ctxt where requestLens = req instance HeistContext Ctxt where getHeist = _heist
It holds a pool of database connections and the state for our Heist templates as well as the FnRequest.
You pass the context into any function that requires it (routes, handlers, whatever).
In contrast, Yesod, Snap, and Scotty are few examples of popular Haskell web frameworks that use "monad transformer stacks" to represent the state of an application.
[Caption: Transformers robots representing monad transformers. Sadly not stacked. The one that turns into a gun is definitely IO.]
So why doesn’t Fn have types like StateT Ctxt IO a instead of Ctxt -> … -> IO a? If everyone else is using monad transformers, what makes us think our way is better?
For beginners, it’s pretty easy to justify -- you can understand everything about Fn without needing to understand monad transformers, and you can use Fn with only a basic understanding of the IO and Maybe monads.
That seems absolutely worth the tradeoff of having to pass ctxt to functions.
For advanced programmers, it’s a little bit more subtle, but still important.
It essentially boils down to wanting Fn to interact as seemlessly as possibly with non-Fn code.
If we were in StateT Ctxt IO a every time we call a function in IO, we have to call lift or liftIO. So there are places where it cuts down on typing!
Also, related, when writing functions, it encourages you to think if you actually need to have the context.
If you were in StateT Ctxt IO, and want to write a helper, the easiest thing is for it to be in the same monad, which means by default you’re building up functions that are, by definition, harder to re-use (as they all need a Ctxt to run). You can, of course, write helpers in IO, but then you need to call them with liftIO, and you may need to figure out how to extract whatever piece of the Ctxt that the helper needs (for example, if you have a helper that just needs to use the database connection).
In contrast, when you already have a Ctxt in scope, and you are in the IO monad, it is harder to write a helper that needs the Ctxt (as you have to pass it in! So strictly more typing!), so if your helper doesn’t need it, that’s great! Also, it is essentially as easy to write a helper that just needs a subset of the Ctxt than a helper that needs the whole thing. So it also encourages you to have less coupled functions.
Finally! it makes it (slightly) easier to re-use these functions outside of the context of Fn. You can call with myFunction ctxt arg1 arg2 rather than runStateT ctxt $ myFunction arg1 arg2.
For advanced programmers, it’s all pretty marginal, but in our opinion, the margins favor our decision.
And for beginners, it’s an absolute win. So, slight win for advanced programmers, massive win for beginners = win.
The two segments mean that it matches two path segments after 'add' (e.g. niceapp.com/add/10/20 ) and parses those segments into function parameters of the type specified in the handler:
addH :: Ctxt -> Int -> Int -> IO (Maybe Response) addH _ x y = okText $ pack . show $ x + y
or:
blendH :: Ctxt -> Text -> Text -> IO (Maybe Response) blendH _ "blue" "red" = okText "Purple!" blendH _ _ _ = errorText "I don't know how to blend those. -_-"
Or if you make a Color type that’s an instance of Fn’s `FromParam` type class, you could write something like:
blendH :: Ctxt -> Color -> Color -> IO (Maybe Response) blendH _ Blue Red = okText "Purple!" blendH _ _ _ = errorText "I don't know how to blend those. -_-"
We wanted our app to start pushing every request to HTTPS redirecting any HTTP requests. ELBs can redirect, so we set up a little NGINX on our app server instances to redirect any requests to port 81 to 443. That way the rails server can sit obliviously on 80 and answer requests.
Configuring the ELB from EB is totally broken. This page is not very useful:
So we hopped over to the underlying EC2 config. Once there, you can find the relevant ELB and edit the listeners. ELB port 80 to instance port 81 and ELB port 443 to instance port 80:
But then you need to poke some holes in the security groups to allow all these new ports. For the ELB security group you need to allow traffic from port 443:
And you need to allow the ELB to send traffic on port 81:
And the instance security group needs to allow traffic from port 81: