【问题标题】:Is it possible to use frege with Play framework是否可以将 frege 与 Play 框架一起使用
【发布时间】:2015-11-18 18:50:21
【问题描述】:

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

我还想要一门函数式编程语言。我可以在 Haskell(因为它很酷)和 Scala(因为 Play Framework)之间进行选择。

经过一些研究以找出这与语言之间的主要区别,我发现了 Frege,一种在 JVM 上运行的类似 Haskell 的语言。

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

【问题讨论】:

  • 请注意,frege 在 SO 上有自己的标签。我相应地更改了标签,因为可能在 Haskell 线程中闲逛的人对此不能说太多。连我都答不上来,因为我不知道 wtf PLAY 是什么。
  • 这绝对是可能的。如果可以使用 Java,将其移植到 Frege 就不会那么难了。我曾经将an Akka example 移植到弗雷格。我将尝试与 Frege 一起玩,稍后再发布一个示例,因为我现在不是我的电脑。
  • @Marimuthu 从我对这种语言的了解来看,每个外部对象和函数都必须在代码中的某个地方声明为对 JVM 上现有实现的本机调用(这似乎合乎逻辑)。所以我想我必须添加我想要使用的 evry Play API 对象的定义。我说的对吗?
  • @EmrysMyrooin 是的。您可以逐步进行,只需定义您真正需要的类型(并且在类型中只定义您真正需要的方法)。或者您可以使用 native-gen 工具一次完成所有操作。但是,后期通常需要一些检查和人工维护。
  • 这是工作项目还是爱好项目?如果是为了工作,我建议只使用 scala。否则,为什么不看看生锈呢?

标签: java scala playframework jvm frege


【解决方案1】:

这是一个简单的应用程序,用于演示我们如何在 Play 中使用 Frege。由于 Play 支持 Java,因此使用 Frege 的 Java API 实际上非常容易,即使我们还没有对 Frege 的原生 Play 支持。该应用程序基本上是 JSON 输入和 JSON 输出。 Frege 程序从 JSON POST 请求中读取参数,并以向用户致意的 JSON 响应进行响应。

播放conf/routes:

POST     /greet                      helloplay.FregeApplication.greet()

现在是 Frege 中的实际“业务逻辑”:

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 框架,因此我们必须为 Frege 添加本机绑定,提及它们的纯度或可能的空值等. 这是一件好事,因为 Frege 是一种纯语言并且没有 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

【讨论】:

  • 伟大的工作,一如既往,Marimuthu!不过,我有一个问题:为什么我们不能只说 request.body.asText 而不是 toJson.toString
  • 好吧,它似乎可以工作,但我认为它有点 hacky...我想将它用于一个工作和严肃的项目,我在这里放松了一些自动化能力,欢迎购买像 JSON 解析这样的播放框架和数据库管理。但对于一些个人项目,我不介意,等待播放端口开放
  • 感谢英戈!我先尝试过,但它似乎不适用于 JSON 请求。
  • @Emrys 够公平的。是的,有了原生播放支持,您将获得所有这些自动化,但我不认为这里有任何 hacky。当然,我可以理解您不想在工作项目中执行此操作,但作为 JVM 语言,您可以将 Frege 与您的 Java 和 Scala 代码混合使用,并从纯 FP 中获得一些好处。如果您尝试一下,我很乐意收到您的反馈。
  • 是的,我认为我会尝试使用 Play 和 Scala 来完成所有 Web 管理工作,并且只将功能部分委托给 Frege 模块。我认为这可能很酷
猜你喜欢
  • 1970-01-01
  • 2018-02-14
  • 1970-01-01
  • 2015-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
  • 1970-01-01
相关资源
最近更新 更多