Singpolyma

MK Dating Adventure

Posted on

In mid-November, I made the decision to try out the online dating site OkCupid. This resulted in my first ever modern-North-American-style formal dating adventure. This post is something of a retrospective + lessons learned from my cross-cultural perspective. I have done some external research before, during, and after the adventure, but all of the information is highly anecdotal.

Before I say anything else, I will say that I think every TCK should experience their host culture’s most common dating practise sooner after re-entry. It’s a very eye-opening experience and can give you a whole new perspective on this decently-important aspect of the culture around you. If you, like me, find the structure of a formal dating experience crazy, you’re not very wrong, but you should try it anyway. You just can’t really understand anything you hear about it (probably including the contents of this post) until you try it.

The One Thing

If I have identified anything as the “most important” about the whole adventure, it’s that you have to really try. You can’t dabble, or hold back to protect yourself, or anything like that. You must be emotionally available, and willing to bend your normal system of existence in order to be in the other person’s world. This is basically the same as with any other cultural integration experience.

In my case, this involved things like more emotional availability than I normally afford to most friends, heavy Facebook usage, etc. While it was going on I felt like I was following this principle pretty well, though of course in hindsight there were tons of ways I could have done even better.

Online Dating

As I said, online dating was also a part of my particular adventure. If your biggest obstacle to this particular cultural experience is finding someone to try it with, then this may be a good option for you. I tried the site OkCupid, mostly because of their OkTrends blog (even though that has been defuct for ages, it’s still awesome) and because it’s free, so I could try it with no obligation. This is super useful if you’re not sure you want to try it out. The site does a very good job of being fun to use, and I found the various pseudo-gamified elements highly addicting. They do have some really crazy nonsense that’s part of the system (they come up with things to email you about all the time, just in case you weren’t planning to come back to the site. For example, everyone early on gets a “people on OkCupid want you so bad” email, and at some point I even got a “our system has determined that you’re hot” email, which may be the most hilarious email I’ve ever received), but in general that just adds to the amusement.

On the other hand, from talking to other online dating users, I cannot characterize my experience as normal. I played around with the site for only threeish days before someone awesome popped out of the woodwork with an expression of interest. I followed up, and things just sort of went well from there. I’m told this is the furthest from normal you can get, and I put it down to God’s purpose.

Being Creepy is Ok

The first super shocking thing I learned is that it’s considered totally acceptable to use all of your Google-fu, etc, to find out as much as you like about the other person, so long as you don’t use that information in an overly creepy way.

When making conversation, this can give you a tonne of fodder for what the right questions to ask are, so use it to your advantage.

Clarify Expectations

Something you should do by the end of the first date is make sure you’re both on the same page as to what this is and where it is going. Ask your date what they’re looking for, and on what sort of timeframe they usually operate. First dates are culturally constructed to allow these sorts of awkward questions to be asked of complete strangers with fairly little fear, and I can tell you that not knowing is way more stressful than asking the question will be.

Don’t go into this with the expectation “I’m just trying this out as an experiment”, though. That violates the One Thing.

Facilitate Conversation

You have a wealth of life experiences, but it’s way more fun to learn about someone else than to talk about yourself. Don’t be secretive about your past, but try not to use it as a conversation starter. Use what you know to draw the other person into talking.

Telling Your Friends

I paired this adventure with an experiment in being much more open about my personal life with friends and co-workers. This may enhance your experience, or it may bias your results, or both, YMMV. One thing that I discovered is that your friends bring their own cultural baggage into the conversation. The mere fact that you find your date worth talking about led, in my case, to a whole different sort of conversation (as if about a budding relationship instead of a formal date with a stranger) with many people. As above, if you plan to involve your friends, set expectations. You can never communicate too clearly.

Have Fun

This is not the same as the age-old “be yourself” advice. Be anyone you want to be. This is actually the perfect opportunity to try out minor behaviour modifications on an unbiased judge, if you like that kind of thing. I mean, don’t lie, but you don’t have to be just like you are with your friends.

Make a Move

This one I’m the least sure about, and comes mostly from research. I did not do it at all, and while it may have gone better if I had, I don’t really have enough information to say. The idea is that by the end of even the first date, you should be flirting. Be interested. This seems pretty in line with the One Thing.

The End

It is possible that your dating adventure will turn into a budding relationship with all the 1000 of pleasures and new experiences (learn more at https://poppersbuyersclub.com/). But let’s be realistic, you’re shoving yourself together with a stranger and then seeing what happens. This is most likely going to end before you get that far. However, you cannot operate as though this is the case, because that would violate the One Thing.

If you follow the One Thing at all, this is going to suck a bit. Unless you call it off, but why would you do that? That definitely violates the One Thing. Anyway, it’s not at all like a breakup, it’s not even as bad as every time you moved away from all your friends for the nth time, and being accustomed to people coming and going will certainly make it suck less. That said, you’ve invested some amount of your emotional existence in this, so when it stops you’ll probably have a few days of turmoil.

One thing I learned here, and I have confirmed this from many sources at this point, is that it’s not only acceptable, but totally normal to end a formal dating relationship by simply not replying to messages anymore. So if you’re texing or facebooking you just get dead air. If you’re calling they dodge your calls / send you to voicemail. If this happens to you, I’m not sure what to suggest. You can’t know right away that it’s over. I slowly escalated my attempts to contact the other person over several communications mediums until I did elicit a response. YMMV. Try to use other indicators to see if this is the case. For example, a few days after my date stopped messaging me, she changed her profile picture on OkCupid, which was a pretty dead giveaway that the adventure had come to a close. Use discretion, and if you’re anything like me and simply must know for sure, try to deal without hyperventilating.

Also, it may be your instict to say “no big deal, I never really expected this to end in a relationship” and file the other person as one of your extended contacts, or even move to try and pull them is as friends. That’s not a rediculous thing to want (you’ve found a person that it’s fun to hang out with, why wouldn’t you want to do more of that?), but there’s something about the nature of the adventure that means the other person is very likely not interested in that. Something to keep in mind.

Next Steps

So, that’s it. I had fun. I learned a lot. I met someone new. I have (I think) a better understanding of my host culture. I actually feel better about myself as a person, just because a stranger was interested enough to message me for weeks and hang out with me twice. I know that she dropped into my life at basically the perfect moment.

I wasn’t really intending to go on this adventure, so I don’t have a plan other than “back to business as usual”. Some people have asked me if I would use this mode again. As you can tell, I’ve never really been a fan, but I might consider it. It’s a terrible way to find a mate, but as long as expectations are clear it’s an ok way to spend some time, and you never know. So, not planning on it, but I still suggest you try it once.

Making A Website With Haskell

Posted on

This is a guide to building simple webapps using Haskell (modelled after this article on a different framework). We will use:

  • WAI (Web Application Interface, and various utilty packages) for the backend
  • mustache2hs for templating
  • sqlite-simple for database access

Getting set up

There is a very useful utility for building Haskell called Cabal, which will allow you to track which versions of which dependencies you are using, and will tell you if they are not properly installed, etc. Create a project.cabal config file, like so:

name:            project
version:         0.1.0
cabal-version:   >= 1.8
category:        Web
copyright:       © 2013 Your Name
author:          Your Name <youremail@example.com>
maintainer:      Your Name <youremail@example.com>
stability:       experimental
synopsis:        My awesome todo-list app
homepage:        http://github.com/yourName/repoName
build-type:      Simple
description:
        A longer description of my awesome app

executable Main
        main-is: Main.hs

        build-depends:
                base == 4.*,
                http-types,
                wai,
                wai-util,
                wai-dispatch,
                yesod-routes,
                warp,
                text,
                path-pieces

source-repository head
        type:     git
        location: git://github.com/yourName/repoName.git

cabal configure will check that you have everything installed cabal build will build your project.

You may want to set up a Makefile, like so:

GHCFLAGS=-Wall -fno-warn-name-shadowing -XHaskell98 -O2

dist/build/project/Main: project.cabal dist/setup-config Main.hs
    cabal build --ghc-options="$(GHCFLAGS)"

dist/setup-config: project.cabal
    cabal configure

.PHONY: clean

clean:
    find -name '*.o' -o -name '*.hi' | xargs $(RM)
    $(RM) -r dist dist-ghc

Hello World

Save this as Main.hs:

module Main (main) where

import Network.Wai.Handler.Warp (run)
import Network.HTTP.Types (ok200)
import Network.Wai.Util (string)

main = run 3000 (\_ -> string ok200 [] "Hello, World!")

Now make and run it:

cabal build
dist/build/bin/Main

Go to http://localhost:3000 and you should see your Haskell site!

Routing

Our previous app gave the same response to every request. We will use the routeGenerator utility to create fast, compiled routes from a simple syntax:

cabal install route-generator

Add the following rule to your Makefile:

Routes.hs: routes
    routeGenerator -r -m Application $< > $@

You will want a file named routes with your routing information in it.

The router supports any possible HTTP method:

GET / => homePage
POST / => postPost
PURCHASE / => buyTheThing

Where the names on the right-hand side are the names of functions in your Application.hs module.

You can also capture parameters:

GET /post/: => showPost

Here’s an example of an Application.hs with handlers for these routes:

module Application where

import Network.HTTP.Types (ok200, notFound404)
import Network.Wai (Application)
import Network.Wai.Util (string)

homePage :: Application
homePage _ = string ok200 [] "Hello, World!"

postPost _ = string ok200 [] "You posted!"

buyTheThing _ = string ok200 [] "Bought it!"

showPost arg _ = string ok200 [] arg

on404 _ = string notFound404 [] "Not found"

And run the whole thing, with the proper 404, like so:

module Main (main) where

import Network.Wai.Handler.Warp (run)
import Network.Wai.Dispatch (dispatch)
import Application
import Routes

main = run 3000 $ dispatch on404 routes

Headers

Get a header:

import Network.Wai.Util (bytestring)
import Data.String (fromString)
import Data.Maybe (fromMaybe)
import Data.Monoid (mempty)

homePage req = bytestring ok200 [] (fromMaybe mempty $ lookup (fromString "User-Agent") $ requestHeaders req)

Set a header:

import Network.Wai.Util (stringHeaders')
homePage _ = string ok200 (stringHeaders' [("Content-Type", "text/calendar")]) "Not a calendar ;)"

Content types

Respond with the appropriate content type:

import Network.Wai.Util (handleAcceptTypes, string, json)

homePage = handleAcceptTypes [
        ("text/plain", string ok200 [] "You asked for text, here it is.")
        ("application/json", json ok200 [] ["A JSON", "array"])
    ]

Templates

There are many good templating systems. My favourites are blaze-html and mustache2hs, because:

  1. They give you some type-checking of your templates at compile time.
  2. They are super fast.

To use mustache2hs, first install it:

cabal install mustache2hs

You will need a module to contain the records that you will render out in your template (Records.hs):

module Records where

data HomePageData = HomePageData {
        title :: String,
        username :: Maybe String
    }

And an actual template to render (homePageView.mustache):

<html>
    <head>
        <title>{{title}}</title>
    </head>
    <body>
        <h1>{{title}}</h1>

        {{#username}}
            Welcome, {{username}}!
        {{/username}}
    </body>
</html>

Set up your Makefile to generate the code:

MustacheTemplates.hs: Records.hs homePageView.mustache
    mustache2hs -m Records.hs homePageView.mustache HomePageData > $@

And actually render it out:

import Network.Wai.Util (stringHeaders', textBuilder)
import MustacheTemplates

htmlEscape :: String -> String
htmlEscape = concatMap escChar
    where
    escChar '&' = "&amp;"
    escChar '"' = "&quot;"
    escChar '<' = "&lt;"
    escChar '>' = "&gt;"
    escChar c   = [c]

homePage _ = textBuilder ok200
    (stringHeaders' [("Content-Type", "text/html; charset=utf-8")])
    (homePageView htmlEscape $ HomePageData "My Title" Nothing)

Logging Requests

If you want to see a log of all requests on standard out, you’ll need to change Main.hs to use a middleware:

import Network.Wai.Middleware.RequestLogger (logStdoutDev)

main = run 3000 $ logStdoutDev $ dispatch on404 routes

Serving Static Content

If you want to serve a directory of static content alongside your app, you can use a fallback mechanisms from the wai-app-static package:

import Network.Wai.Application.Static (staticApp, defaultWebAppSettings)
import Filesystem (getWorkingDirectory)

staticRoot = staticApp . defaultWebAppSettings

main = do
    cwd <- getWorkingDirectory
    run 3000 $ dispatch (staticRoot cwd) routes

Or alternately use the middleware from wai-middleware-static:

import Network.Wai.Middleware.Static (static)

main = run 3000 $ static $ dispatch on404 routes

Sessions

Some apps need a way to store data between requests using cookies. wai-session is a package that provides a generic way of doing this, and has existing backends for in-memory storage, encrypted cookies, and tokyocabinet. The wai-session-clientsession package contains the backend for encrypted cookies:

module Main where

import Data.Default (def)
import Data.Maybe (fromMaybe)
import Data.String (fromString)
import qualified Data.Vault as Vault

import Network.Wai
import Network.Wai.Util (string)
import Network.Wai.Handler.Warp (run)
import Network.HTTP.Types (ok200)
import Control.Monad.Trans.Resource (ResourceT)

import Web.ClientSession (getDefaultKey)
import Network.Wai.Session (withSession, Session)
import Network.Wai.Session.ClientSession (clientsessionStore)

app session env = do
    u <- sessionLookup "u"
    sessionInsert "u" (show $ pathInfo env)
    string ok200 [] $ fromMaybe "Nothing" u
    where
    Just (sessionLookup, sessionInsert) = Vault.lookup session (vault env)

main = do
    session <- Vault.newKey
    store <- fmap clientsessionStore getDefaultKey
    run 3000 $ withSession store (fromString "SESSION") def session $ app session

Databases

For database access, use postgresql-simple or sqlite-simple:

import Database.SQLite.Simple (open, close, query, Only(..))
import Database.SQLite.Simple.FromRow (FromRow(..))

data Post = Post {
        postTitle :: String,
        postBody :: String
    }

instance FromRow Post where
    fromRow = Post <$> field <*> field

showPost :: Int -> Application
showPost postId _ = do
    conn <- open "./production.sqlite3"
    [post] <- query conn "SELECT * FROM posts WHERE post_id = ?" (Only postId)
    string ok200 [] (postTitle post)
    close conn

Of course, you shouldn’t probably re-connect on every request. Change your Makefile to have the router pass an argument through:

Routes.hs: routes
    routeGenerator -r -n 1 -m Application $< > $@

And do the connection from Main.hs:

import Database.SQLite.Simple (open, close)

main = do
    conn <- open "./production.sqlite3"
    run 3000 $ dispatch on404 (routes conn)
    close conn

And then you can use the connection:

showPost :: Connection -> Int -> Application
showPost conn postId _ = do
    [post] <- query conn "SELECT * FROM posts WHERE post_id = ?" (Only postId)
    string ok200 [] (postTitle post)

Deploying to Heroku

Deploying to Heroku is easy with the heroku buildpack.

First, our hello world app needs to change slightly. Heroku tells us what port to run on with the PORT env variable:

module Main (main) where

import System.Environment (getEnv)
import Network.Wai.Handler.Warp (run)
import Network.HTTP.Types (ok200)
import Network.Wai.Util (string)

main = do
    port <- fmap read $ getEnv "PORT"
    run port $ string ok200 [] "Hello, World!"

Then add a Procfile in your root dir to tell Heroku how to start your app:

web: ./dist/build/project/Main

And add a Setup.hs to build your app:

import Distribution.Simple
main = defaultMain

Then, assuming your project is a git repo:

heroku create --stack=cedar --buildpack https://github.com/pufuwozu/heroku-buildpack-haskell.git
git push heroku master

DEFCON Reflection

Posted on

This year, for the first time, I attended the security convention and hacker party time that is DEFCON.

I had heard a lot of things about DEFCON, but it far exceeded my expectations. The convention is so full of things to do that most of the time I was not even aware of them all. Atendees are, mostly, intelligent, approachable, and respectful.

On Thursday, within 10 minutes of setting up an account for the secure wireless (by using the inscure wireless), my Blackberry Z10 went nuts. I took a device that didn’t have any data on it on purpose so that I could be reckless like this. I was impressed by the speed and violence of the attack. I could not turn my phone off properly (it just kept vibrating and making noises) and had to remove the battery. Booting in airplane mode was fine, but the moment I connected to the WiFi again the attack continued. Creating an actually secure account using a friend’s 3G allowed me to actually use my phone for the rest of the convention. Overall, it was an awesome experience.

I saw talks about quadcopters, Dust, ToR, SIM card exploits, physical lock exploits (as well as normal lockpick techniques). I attended workshops on evidence tampering and handcuff shimming. I spent some time trying to decode some of the crypto puzzles that were an integral part of the conference. I met some people.

The reputation DEFCON has for being full of misogyny and therefore having few female attendees is completely overblown. I was actually suprised at the (seemingly) huge number of female attendees, compared to many other tech conferences I have participated in. Hacker Jepordy has a stripping component, and that was the only anti-feminism I saw at the convention. I saw a lot more, but that was Vegas casinos, and not inside the convention space.

The weather was amazing. Hot and dry. The air conditioning way overcompensates, though (my hotel room was set to 19 when I arrived), so take a warm shirt.

Overall I enjoyed myself, and I plan to go back again next year.

On Insurance

Posted on

Most people in the west are familiar with the idea of insurance. Most of us pay at least one insurance policy. What is it that we really hope to be accomplishing by this?

Insurance works by having customers pay fees in return for protection against some money-related disaster. When a specified disaster (such as a car crash) happens, the insurance company then pays (some of) the cost. The idea is that you would not be able to afford this unexpected disaster, and the insurance company takes that burden off of you. If nothing bad ever happens, then you just keep paying.

That is, insurance is a bet against yourself. The only way the insurance ever “pays off” is when you experience a disaster. Car insurance is a bet that you will crash. Life insurance is a bet that you will die sooner rather than later. The insurance company itself is actually betting on you. As long as nothing bad happens to their customers (on average), they make money.

So, if you have bad things happen to you all the time, insurance is a good deal. Otherwise, you will end up paying more than it would cost to recover from the disaster, just for the “protection”, in which case a savings account would be a better investment.

Why do we buy insurance, then? Why not just save? Well, the biggest reason is that if some disaster occurs before the savings account has filled up, insurance is a better deal. There is a fear that, if disaster strikes, we might end up in debt (or worse). We want protection. There has to be a better way to get it.

Let’s say I have a barn, and it burns down. I don’t have insurance, and I have not yet saved enough money to build a new barn. I cannot live without a barn (my livelihood depends on it), so I cannot just alter my lifestyle to a barnless lifestyle. A very traditional solution to this problem was/is the barn raising. A barn raising is when the entire community comes together, pools their resources, and rebuilds my barn. Why do they do this? Well, because if their barn burns down I’ll do the same for them. Essentially we are treating our pooled savings (and other resources, primarily manpower) as an on-the-fly insurance pool. This is a bet on the community, because if nothing bad happens, everyone keeps their money.

Barn raisings are great, but they have a problem: what if community members do not save well? What if they want to help, but the money is simply not around? This is where we get another strategy from: pooled community savings. A group of people open a fund together, and pay dues just like they would to an insurance company. Payments are made out of the fund (based on community vote, or similar) when this is a disaster. If the fund has enough money in it, then dues can be lessened or stopped. Members may even be allowed to transfer “their portion” to another fund if there is a good reason. PeerCover and others are doing pretty innovative work in this area.

What strategy to pick depends quite a bit on the situation, and there are a few places where insurance cannot be avoided (car liability insurance is legally mandated in many places), but there are a number of options available. Let’s stop betting against ourselves out of fear.

ARM Tooling Interlude

Posted on

This is just a breif interlude to document something that it took me a very long time to find out. Some ARM cross-compiling toolchains default to thumb instructions. Thumb instructions are this nifty feature of ARM that allow most common instructions to be represented in 16 bits instead of 32 bits, which can save RAM and improve instruction fetching. Many of the instructions needed in the context-switch part of the kernel, however, must be in full 32-bit ARM. No problem, there are instructions for switching the CPU mode, just make it switch whenever moving from one to the other, right?

One of the downsides of writing C over raw assembly is that you don’t have full control over what instructions are output. I needed a way to make the toolchain realize that mode-switching instructions needed to be inserted. I could not (at the time) find such a way.

So, I used a different solution: tell the C compiler to always output 32-bit ARM, no matter what the default is. This worked, but presented another problem: the default and standard libraries for my gcc were also in thumb, and the interwork was not getting set up there either! So I could no longer use anything from libgcc or libc, which meant that not only could I not use their memcpy, etc (not neccessarily bad, since in an OS one might want to write one’s own of much of libc anyway), but I couldn’t use things like the % operator (which on ARM is implemented using a helper procedure in libgcc).

A helpful StackOverflow user finally found the answer for me recently, and I have confirmed that by marking procedure entry points as functions I can stop being concerned about -marm, which allows me to Use -lgcc and % and even use parts of -lc.