Purescript with Vue.js - Fetching Data

Posted on by Mandla Mbuli

I need to be able to fetch data from some URL that returns a list of JSON. The API will have to happen soon. I want to see how I can get data from an API. Since JSON is familiar, I am going to just use it. I wonder if there might be simpler ways since the API will be in Haskell and Purescript is inspired by Haskell.

HTTP GET

A library that I found when I looked at pursuit for making HTTP requests was purscript-affjax. It looked simple enough to use and so I tried it. Since I am still using the “You should not be using this anymore” bower. I installed it thusly (This is instruction from the pursuit page)

bower install purescript-affjax
npm install xhr2

Once this the installation is complete, I modified the HelloWorld.purs file to look like:

module HelloWorld where

import Prelude
import Effect (Effect)
import Effect.Class.Console (log)
import Affjax as AX
import Affjax.ResponseFormat as ResponseFormat
import Data.Argonaut.Core as J
import Data.Either (Either(..))
import Data.HTTP.Method (Method(..))
import Effect.Aff (launchAff)

greet :: String -> String
greet name = "Hello, " <> name <> "!"

main = void $ launchAff $ do
  result <- AX.get ResponseFormat.json "https://jsonplaceholder.typicode.com/todos/1"
  case result of
    Left err -> log $ "FAILED: " <> AX.printError err
    Right res -> log $ "SUCCEEDED: " <> J.stringify res.body

I don’t have the API yet and I am just exploring how to handle fetching data so I am using: https://jsonplaceholder.typicode.com/todos as the API for now. I need to be able to retrieve a list of things and get to the individual properties. The “list of things” at the moment is a list of todo items.

Example:

{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}

Now I want to got though the list returned from /todos and log the titles. From working with Haskell and Elm, I know I have to do some sort of decoding. To do this I found purescript-argonaut-core. It has which does Generic magic to make parsing JSON easier so I just installed it.

bower install --save purescript-argonaut-codecs purescript-validation

I then modify the HelloWorld.purs file to be:

module HelloWorld where

import Prelude
import Effect (Effect)
import Effect.Class.Console (log)
import Affjax as AX
import Affjax.ResponseFormat as ResponseFormat
import Data.Argonaut.Core as J
import Data.Argonaut.Decode as JD
import Data.Either (Either(..))
import Data.List (List, intercalate) 
import Effect.Aff (launchAff)

greet :: String -> String
greet name = "Hello, " <> name <> "!"

type Todo = { userId :: Int
            , id :: Int
            , title :: String
            , completed :: Boolean
            }

decodeTodos :: J.Json -> Either String (List Todo)
decodeTodos = JD.decodeJson

main :: Effect Unit
main = void $ launchAff $ do
  result <- AX.get ResponseFormat.json "https://jsonplaceholder.typicode.com/todos"
  case result of
    Left err -> log $ "FAILED: " <> AX.printError err
    Right res -> log $ "SUCCEEDED: " <> case decodeTodos res.body of
                                             Left err -> err
                                             Right xs -> intercalate ", " $ map (\t -> t.title) xs

The decodeJson function can apparently decode all “primitive” types and the aim is to always get complex types into primitive representation. Hopefully this is not too hard later. For now, I can get a list of things and access specific attributes from them.