How to Send an SMS in Haskell

July 12, 2017
Written by

haskell-twilio

Functional programming languages are gaining in popularity so let’s hop on that Haskell bandwagon. With Haskell, you can write clean, concise, and expressive code. Don’t believe me just yet?

Java program versus Haskell program
The Java and Haskell programs above make two lists: one of all even numbers up to 100, and one of the those same even numbers but without the first five numbers. Which one looks nicer?

Now let’s dive into setting up your Haskell developer environment by

  1. configuring two package managers
  2. installing Haskell
  3. making a “Hello, World” program
  4. sending our first SMS with Twilio using Haskell (get a Twilio phone number here)

IDEs for Haskell

There is no complete Haskell IDE (so if you want to make one, the market is wide open.) Many Haskellers use Atom because it has the language-haskell and ide-haskell packages, whose syntax-highlighting of aspects like import statements make it stand out. They also help with auto-indentation, auto-completion, and identifying types.  My Haskell professor recommends Atom with Emacs which works in terminal and has good syntax highlighting and code-completion. For you Vim fans, never fear: you can set up Vim and Haskell like this. You can also try Eclipse with this colorer plugin or Leksah which is written in Haskell, uses the cabal package format, and offers multi-window support. I however prefer Sublime Text 3 mainly because I’m used to it for web development. It offers a SublimeHaskell package with smart completion, type inference, and error and warning highlighting, and is what was used to make this post.

How to Install Haskell

The interactive Glasgow Haskell Compiler is all open source on GitHub. Install both Haskell and GHC here from a Mac or visit here from a PC. To test it run $ghci on the command line. You should see something like this if all goes well.

Successful Haskell Installation on the Command Line

 

How to Find and Download Haskell Packages

A package is a library of Haskell modules that the compiler recognizes. These modules contain functions and types that can help you solve problems when coding, letting you work with REST APIs (hey, like Twilio!) Where can you find neat Haskell packages to code with? Check out Stackage and Hackage for open-source packages which you download using the stack and cabal package managers. The main difference between the two is that Stackage only offers a subset of the packages Hackage offers. Hackage packages could potentially have dependency issues, but most are completely fine out-of-the-box. Overall, Hackage offers a greater spread and variety to choose from.

Manage Haskell Packages with Stack

Stack is my preferred package manager for Haskell. Stack is isolated; so there are no changes made outside of specific Stack directories when you stack install on the command line. When you build with stack, it makes reproducible builds (also known as package caching) so that stack build does the same thing tomorrow as it does today if none of the code changes. Stack also offers a nice, clean developer experience.

On a Mac machine, type the following on the command line to install:

curl -sSL https://get.haskellstack.org/ | sh

If you’re using Windows, install Stack with this Windows 64-Bit Installer. For more details on Stack, visit their install/update page.

Stack is very nice with setting up your initial project. This next section is run in the terminal and shows how you would get started with a new stack project. Replace anything starting with “your with a name you choose.

stack new your-hask-project #new directory w/ starter files
cd your-hask-project #get into direc.
stack setup #download compiler
stack build #build project
stack install your-hask-package #install an executable package ie Twilio
stack exec your-hask-project #execute project command (start server, run proj, etc)

Manage Haskell Packages with Cabal

The other widely-used Haskell package manager is Cabal. It is included in the Haskell platform which sort of makes you think it would be easier to use…I WISH! Honestly? Many Haskellers I’ve met are not big fans of cabal. My biggest problem with Haskell has been issues with cabal dependencies (also known as cabal hell). What’s the solution to that problem? Sandboxes, which allow developers to isolate and build packages by making a private package environment for each package like in Python’s Virtualenv.

To install cabal, run in the terminal

cabal init  #creates Setup.hs, .cabal file for you, asks questions
cabal sandbox init
cabal install hask-package-you-want
cabal build

Hello World In Haskell

To get Hello World, no packages are needed. On the command line, type ghci and after clicking return, type

putStrLn "Hello, World"

But *gasp* that’s so fast.

Rocky fast run

How about making “Hello, World” from a Haskell file? Make a new directory to put your project in and call it sms. Let’s make a file in it called first.hs and on the first line write

main = putStrLn "Hello World"

Switching back to the command line, type the following to compile your file.

ghc -o hello first.hs

Then run the executable hello by typing on the command line:

./hello 

Voila! You just completed Hello, World two ways in Haskell.

Send an SMS with Haskell

First, get a Twilio phone number that can receive text messages. You can do that here if you don’t have one already.

You’ll need your Twilio Account SID and Auth Token to send texts. Grab those from your console, and store them as environment variables. If you’re on a Windows-based system, see this post to do that. In a unix-based system, you would set them up by typing the following two lines in your shell and add them to your  .bash_profile.

export TWILIO_ACCOUNT_SID="YOUR_ACCOUNT_SID"
export TWILIO_AUTH_TOKEN="YOUR_AUTH_TOKEN"

On the command line in your sms directory run stack new sms.  This will set up our project with files like sms.cabal, stack.yaml, Setup.hs, and Main.hs. In the file sms.cabal, find the line which begins with build-depends of the executable and remove the line beginning withbuild-depends which is there. Put the following in that space instead to use Twilio:

build-depends: base
 , twilio
 , transformers

Next on the command line type stack init --solver so that stack can determine a package set compatible with your sms.cabal file. Following that, in whichever IDE you would like (see above thoughts on that), open up the directory you just made.

Now open up Main.hs (located in the app folder) and erase whatever code is already there. In its place type the following code. Because we’re sending our first SMS, update the following with the phone numbers you wish to send a SMS to and your own Twilio phone number:

{-#LANGUAGE OverloadedStrings #-}
module Main where
import Control.Monad.IO.Class(liftIO)
import System.Environment (getEnv)
import Twilio
import Twilio.Messages
main:: IO()
main = runTwilio' (getEnv "TWILIO_ACCOUNT_SID")
                  (getEnv "TWILIO_AUTH_TOKEN") $ do
  let body = PostMessage "NUMBER_TO_TEXT" "YOUR_TWILIO_NUMBER" "Hello, World!"
  message <- post body
  liftIO $ print message

Open up a fun Hacker News article to read because this next step will take a little bit of time. On the command line, type

stack build

Waiting Silicon Valley gif

Once it’s done, let’s run the executable by typing on the command line

stack exec sms-exe

SUCCESS! You should have just sent a SMS message in Haskell and now see this in your terminal:

Success SMS sent message in terminal

If you get an error like“getEnv: does not exist (no environment variable),” make sure your environment variables are set correctly and check your corresponding variable names. Then open up a terminal window and run

source ~/.bash_profile

Learn more about Haskell

Want to learn more about Haskell in general? I recommend Learn You a Haskell and O’Reilly’s Real World Haskell. Stay tuned for more Haskell posts to learn more about this functional language, and let me know what you think of any IDEs, cabal or stack, or Haskell in general online.

Email: lsiegle@twilio.com

GitHub: elizabethsiegle

Twitter: @lizziepika