packages feed

Rlang-QQ-0.2.0.0: examples/tests.hs

{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE DataKinds, PolyKinds, FlexibleContexts, TemplateHaskell, QuasiQuotes #-}
module Main where
import Test.Hspec

import System.Directory
import RlangQQ
import GHC.TypeLits
import Control.Lens

import Control.Monad
import qualified Data.Vector as V

makeLabelable "x y z"

inRecL = hLens' (Label :: Label "inRec")

inRec = [pun| x y z |] where
    x = "xlabel"
    y,z :: [Double]
    y = [1,2,3]
    z = [3,2,1]


main = hspec $ describe "rlangqq" $ do
  it "can read a tsv file" $ do
      [pun| x@(a b) s |] <- [r|
        # find the file whether we runghc tests.hs
        # runghc examples/tests.hs
        fname <- c(Sys.glob('*.tsv'), Sys.glob('examples/*.tsv'))[1]
        hs_x <- as.list(read.delim(fname, sep=' '))
        hs_s <- as.numeric(with(hs_x, t(a) %*% b))
        |]
      (V.sum (V.zipWith (*) a b) :: Double, s :: Double)
        `shouldBe` (93.783, 93.783)

  it "does the same as zipWith" $ do

      o <- [r| print(hs_inRec) # should be unnecessary
               hs_inRec <- within(hs_inRec, y <- y + z) |]
      let inR = hLens' (Label :: Label "inRec")
      (o ^.inR.y) `shouldBe` zipWith (+) (inRec^.y) (inRec^.z)
  
  it "accumulates when variables are ch_" $ do
        w <- newRChan
        [r|
            print(hs_inRec) # this shouldn't be necessary to force INOUT
            hs_inRec <- within(hs_inRec, y <- y + z + ch_w) |]

        out <- forM [1,2,3,4 :: Double] $ \n -> do
                sendRcv w n <&> view (inRecL . y)
        out `shouldBe`
          tail (scanl
                    (\ accum n -> map (+n) $ zipWith (+) (inRec^.z) accum)
                    (inRec^.y)
                    [1 .. 4])

  it "repeats when variables are not ch_" $ do
      out <- forM [1,2,3,4 :: Double] $ \n -> do
          [r| print(hs_inRec) # this shouldn't be necessary to force INOUT
              hs_inRec <- within(hs_inRec, y <- y + z + hs_n) |]
            <&> view (inRecL . y)
      out `shouldBe`
       map (\n -> map (+n) (zipWith (+) (inRec^.y) (inRec^.z))) [1 .. 4]
    
  it "interpolates haskell expressions" $ do
        ys <- forM [1,2,3,4 :: Double] $ \n -> do
            [pun| inRec{y} |] <- [r| # this shouldn't be necessary to force INOUT
                        print(hs_inRec)
                        hs_inRec <- within(hs_inRec, y <- y + z + $(n+1)  ) |]
            return y
        ys `shouldBe` map (\n -> map (+(1+n)) (zipWith (+) (inRec^.y) (inRec^.z))) [1 .. 4]

  it "can make a plot where you ask it to" $ do
      let x = [0 .. 10  :: Double]
          y = map (sin . (*pi) . (/10)) x
      b <- doesFileExist "testplot.png"
      when b (removeFile "testplot.png")
      -- normally you would just call qplot, and find a plot in Rtmp/figN/...
      [r| library(ggplot2)
          print('blahh')
          png(file='testplot.png')
          plot(qplot( hs_x, hs_y ))
          dev.off()
          |]
      doesFileExist "testplot.png" `shouldReturn` True