是否可以将 frege 与 Play 框架一起使用
Is it possible to use frege with Play framework
我正在为一个新项目搜索一种语言。这是一个基于网络的项目,我想采用 REST 架构。
我也想要一门函数式编程语言。我可以在 Haskell(因为它很酷)和 Scala(因为 Play Framework)之间做出选择。
经过几次研究以找出这与语言之间的主要区别后,我发现了 Frege,一种在 JVM 上 Haskell 类语言 运行。
所以我的问题是,因为 Frege 在 JVM 上 运行,是否可以将 Play 框架与 Frege 一起使用?
这里有一个简单的应用程序来演示我们如何在 Play 中使用 Frege。由于 Play 支持 Java,实际上很容易使用 Frege 的 Java API,即使我们还没有对 Frege 的原生 Play 支持。该应用程序基本上是 JSON-in 和 JSON-out。 Frege 程序从 JSON POST
请求中读取一个参数,并用 JSON 响应来响应用户。
播放 conf/routes
:
POST /greet helloplay.FregeApplication.greet()
现在弗雷格的实际"business logic":
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()))
);
}
}
这里我们定义了2种对应于请求和响应的类型,以及JSON转换FromJSON
和ToJSON
类型的class实例。 webMain
函数获取 play Request
并从 JSON 请求和 returns 中读取 name
JSON 响应包装在 play 的 Result.Status
.
webMain
函数是为 Play 控制器提供实现的函数。播放控制器是 class,它扩展了播放的 play.mvc.Controller
。我们可以通过在 Frege 源文件中声明 native module
来使 Frege 模块扩展 Java class。 webMain
函数也是一个 IO 操作,因此我们必须在某个时刻评估是否会发生某些事情,这就是底部控制器中的 Java 方法通过调用 Frege 的 ST.performUnsafe
和然后从可能的 thunk 强制结果,否则应用程序只会预热 CPU :)
这里Request
、ResultStatus
、PlayController
等类型和ok
、badRequest
等函数都来自Play框架,所以我们必须添加Frege 的本机绑定提及它们的纯度或可能的空值等。这是一件好事,因为 Frege 是一种纯语言并且没有 null
的概念,我们必须明确提及副作用或 Maybe
与 Scala 不同的是编译器可能的 null 值,在 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"}
弗雷格有一个 SBT plugin that can be used to compile Frege sources in a Play project. I have pushed this sample application in Github 如果有人想尝试的话。
我正在为一个新项目搜索一种语言。这是一个基于网络的项目,我想采用 REST 架构。
我也想要一门函数式编程语言。我可以在 Haskell(因为它很酷)和 Scala(因为 Play Framework)之间做出选择。
经过几次研究以找出这与语言之间的主要区别后,我发现了 Frege,一种在 JVM 上 Haskell 类语言 运行。
所以我的问题是,因为 Frege 在 JVM 上 运行,是否可以将 Play 框架与 Frege 一起使用?
这里有一个简单的应用程序来演示我们如何在 Play 中使用 Frege。由于 Play 支持 Java,实际上很容易使用 Frege 的 Java API,即使我们还没有对 Frege 的原生 Play 支持。该应用程序基本上是 JSON-in 和 JSON-out。 Frege 程序从 JSON POST
请求中读取一个参数,并用 JSON 响应来响应用户。
播放 conf/routes
:
POST /greet helloplay.FregeApplication.greet()
现在弗雷格的实际"business logic":
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()))
);
}
}
这里我们定义了2种对应于请求和响应的类型,以及JSON转换FromJSON
和ToJSON
类型的class实例。 webMain
函数获取 play Request
并从 JSON 请求和 returns 中读取 name
JSON 响应包装在 play 的 Result.Status
.
webMain
函数是为 Play 控制器提供实现的函数。播放控制器是 class,它扩展了播放的 play.mvc.Controller
。我们可以通过在 Frege 源文件中声明 native module
来使 Frege 模块扩展 Java class。 webMain
函数也是一个 IO 操作,因此我们必须在某个时刻评估是否会发生某些事情,这就是底部控制器中的 Java 方法通过调用 Frege 的 ST.performUnsafe
和然后从可能的 thunk 强制结果,否则应用程序只会预热 CPU :)
这里Request
、ResultStatus
、PlayController
等类型和ok
、badRequest
等函数都来自Play框架,所以我们必须添加Frege 的本机绑定提及它们的纯度或可能的空值等。这是一件好事,因为 Frege 是一种纯语言并且没有 null
的概念,我们必须明确提及副作用或 Maybe
与 Scala 不同的是编译器可能的 null 值,在 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"}
弗雷格有一个 SBT plugin that can be used to compile Frege sources in a Play project. I have pushed this sample application in Github 如果有人想尝试的话。