是否可以在Play框架中使用frege

时间:2015-11-18 18:50:21

标签: java scala playframework jvm frege

我正在搜索一个新项目的语言。这是基于Web的项目,我想采用REST架构。

我还想要一种函数编程语言。我可以选择Haskell(因为它很酷)和Scala(因为Play Framework)。

经过一些研究发现它与语言之间的主要区别后,我找到了Frege,一种在JVM上运行的Haskell语言。

所以我的问题是,因为Frege在JVM上运行,是否可以将Play框架与Frege一起使用?

1 个答案:

答案 0 :(得分:5)

这是一个简单的应用程序,用于演示如何将Frege与Play结合使用。由于Play支持Java,实际上很容易使用Frege的Java API,即使我们还没有对Frege的本机Play支持。该应用程序基本上是JSON-in和JSON-out。 Frege程序从JSON POST请求中读取参数,并使用迎接用户的JSON响应进行响应。

播放conf/routes

POST     /greet                      helloplay.FregeApplication.greet()

现在弗雷格的实际“业务逻辑”:

module helloplay.FregeApplication where

import Data.JSON
import helloplay.Play

data GreetingRequest = GreetingRequest { name :: String }

data GreetingResponse = GreetingResponse { message :: String }

instance FromJSON GreetingRequest where
   fromJSON (Struct fs)  = do
        name <- field "name" fs
        pure $ GreetingRequest name
   fromJSON invalid = fail ("Invalid JSON for Greeting Request: " ++ show invalid)

instance ToJSON GreetingResponse where
    toJSON (GreetingResponse message) = Struct [ assoc "message" message ]

greet :: GreetingRequest -> GreetingResponse
greet request = GreetingResponse $ "Hello, " ++ request.name

webMain :: Request -> IO ResultStatus
webMain request = do
  let jsonRequest = parseJSON request.body.asJson.toString
  return $ either badRequest (ok . show . toJSON . greet) jsonRequest

{-
 - This makes the Frege module extend Play Controller class so that it can be configured to handle a route.
 -}
native module type PlayController where {
    public static play.mvc.Result greet() {
        return frege.runtime.Delayed.forced(
          frege.prelude.PreludeBase.TST.performUnsafe(webMain(request()))
        );
    }
}

在这里,我们为FromJSONToJSON类型类实例的用户定义了与请求和响应以及JSON转换相对应的2种类型。 webMain函数接受播放Request并从JSON请求中读取name并返回包含在播放Result.Status中的JSON响应。 webMain函数是为Play控制器提供实现的函数。播放控制器是一个扩展Play play.mvc.Controller的类。我们可以通过在Frege源文件中声明native module来使Frege模块扩展Java类。 webMain函数也是一个IO动作,所以我们必须在某个时候评估一些事情,这是底层Controller中的Java方法通过调用Frege的ST.performUnsafe然后强制结果来做的事情。从一个可能的thunk,否则应用程序将热身CPU:)

此处类似RequestResultStatusPlayController以及okbadRequest等类型都来自Play框架,因此我们必须添加本机绑定因为弗雷格是一种纯粹的语言,并且没有null的概念,所以我们必须明确提到副作用或Maybe为弗雷格提及他们的纯度或可能的空值等。这是一件好事。与Scala不同的编译器可能的空值,您可以在其中调用任何Java方法。

Play的Frege原生绑定:

module helloplay.Play where

data PlayController = native play.mvc.Controller

data Result = pure native play.mvc.Result

data ResultStatus = pure native play.mvc.Results.Status

pure native badRequest play.mvc.Results.badRequest :: String -> ResultStatus

data Request = pure native play.mvc.Http.Request where
  pure native body :: Request -> RequestBody

data RequestBody = pure native play.mvc.Http.RequestBody where
  pure native asText :: RequestBody -> String
  pure native asJson :: RequestBody -> JsonNode

data JsonNode = pure native com.fasterxml.jackson.databind.JsonNode where
  pure native asText :: JsonNode -> String
  pure native toString :: JsonNode -> String

pure native ok play.mvc.Results.ok :: String -> ResultStatus

就是这样!我们可以用:

运行它

activator run

然后

$ curl --header "Content-type: application/json" --request POST --data '{"name": "PlayFrege"}' http://localhost:9000/greet

{"message" : "Hello, PlayFrege"}

Frege有SBT plugin可用于在Play项目中编译Frege源。如果有人想试试,我已经在Github中推送了这个示例应用程序。