caasih.net

Frege #0

想在工作用得上的 side-project 裡試試 Frege 。初衷是:如果大家都在 production 用 FP language ,我也必須這樣。不然經驗永遠不夠,只能把 FP 當玩具。

Frege: Hello Java - mmhelloworld 介紹了如何用 Frege 跟 Java 溝通,可以看到不純的 class 要放在長長的 ST s (Mutable s (ClassName a)) 中,可以簡寫成 STMutable s (ClassName a)

ST s a 的說明可以在 PreludeBase.fr 中找到:

@(ST s a)@ is an abstract data type and is a computation that encapsulates side effects in state thread @s@ and returns a value of type @a@.

配上 talios/frege-testing ,只靠 mvn compile exec:exec 就把程式跑起來!

Frege 社群有個工具, Frege/frege-native-gen ,能幫忙自動產生和 Java classes 溝通的程式碼,但我打算先自己寫幾次,了解 ST s a 到底是什麼、用起來是什麼感覺後,再學工具。

接接看 Apache.POI

來看看要怎麼包 HSSFWorkbook 這種實用的 lib 。

首先我們需要把 Java constructor 包起來:

data HSSFWorkbook = native org.apache.poi.hssf.usermodel.HSSFWorkbook where
  native new :: () -> ST s (Mutable s HSSFWorkbook)

其中 ST s (Mutable s HSSFWorkbook) 可以簡寫STMutable s HSSFWorkbook ,兩個 s 的 type 相同:

data HSSFWorkbook = native org.apache.poi.hssf.usermodel.HSSFWorkbook where
  native new :: () -> STMutable s HSSFWorkbook

接著處理 HSSFWorkbook::write

data HSSFWorkbook = native org.apache.poi.hssf.usermodel.HSSFWorkbook where
  native new :: () -> STMutable s HSSFWorkbook
  native write :: MutableIO HSSFWorkbook -> OutputStream -> IO ()
    throws IOException

MutableIOMutable RealWorld別名IOST RealWorld別名。還有個現在沒出現的 IOMutableIO MutableIO別名


接著還需要產生 HSSFSheet ,在 HSSFWorkbook 中加上 createSheet function :

data HSSFWorkbook = native org.apache.poi.hssf.usermodel.HSSFWorkbook where
  native new :: () -> STMutable s HSSFWorkbook
  native createSheet :: Mutable s HSSFWorkbook -> String -> STMutable s HSSFSheet
  native write :: MutableIO HSSFWorkbook -> OutputStream -> IO ()
    throws IOException

補上其他 type :

data HSSFSheet = native org.apache.poi.hssf.usermodel.HSSFSheet where
  native createRow :: Mutable s HSSFSheet -> Int -> STMutable s Row
  
data Cell = native org.apache.poi.ss.usermodel.Cell where
  native setCellValue :: Mutable s Cell -> String -> ST s ()

data Row = native org.apache.poi.ss.usermodel.Row where
  native createCell :: Mutable s Row -> Int -> STMutable s Cell

處理一下例外:

pure native showThrowable toString :: Throwable -> String

整個寫起來像這樣:

module frege.Main where

data HSSFSheet = native org.apache.poi.hssf.usermodel.HSSFSheet where
  native createRow :: Mutable s HSSFSheet -> Int -> STMutable s Row

data HSSFWorkbook = native org.apache.poi.hssf.usermodel.HSSFWorkbook where
  native new :: () -> STMutable s HSSFWorkbook
  native createSheet :: Mutable s HSSFWorkbook -> String -> STMutable s HSSFSheet
  native write :: MutableIO HSSFWorkbook -> OutputStream -> IO ()
    throws IOException

data Cell = native org.apache.poi.ss.usermodel.Cell where
  native setCellValue :: Mutable s Cell -> String -> ST s ()

data Row = native org.apache.poi.ss.usermodel.Row where
  native createCell :: Mutable s Row -> Int -> STMutable s Cell

pure native showThrowable toString :: Throwable -> String

main _ = do
  let filename = "out.xls"
  workbook <- HSSFWorkbook.new ()
  sheet <- HSSFWorkbook.createSheet workbook filename
  row <- HSSFSheet.createRow sheet 0
  cell <- Row.createCell row 0
  Cell.setCellValue cell "hello, world"
  file <- File.new filename
  out <- FileOutputStream.new file
  try (\book -> HSSFWorkbook.write book out) workbook
    `catch` (\(exception :: IOException) -> println $ showThrowable exception)

再來要挑戰 Vert.x

Isaac Huang 發佈於