2015-11-18 29 views
2

我正在寻找新项目的语言。这是基于Web的项目,我想采用REST架构。是否有可能使用frege与Play框架

我也想要一个函数编程语言。我可以选择Haskell(因为它很酷)和Scala(因为Play框架)。

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

所以我的问题是,因为Frege运行在JVM上,所以可以在Frege中使用Play框架吗?

+2

请注意,frege在SO上有自己的标签。我相应地更改了标签,因为在Haskell线程中闲逛的人可能不会多说这些。即使我不能回答,因为我不知道wtf PLAY是。 – Ingo

+2

它应该是可能的。如果Java有可能,那么把它移植到弗雷格就不那么难。我曾经将一个[Akka示例](http://stackoverflow.com/questions/17256979/akka-with-frege-running-slower-than-scala-counterpart)移植到Frege。我会尝试与弗雷格玩,稍后发布一个例子,因为我现在不是我的电脑。 –

+0

@Marimuthu从我所看到的这种语言中,每一个外部对象和函数都必须在代码中声明为本地调用的现有实现的第JVM(这似乎是逻辑的)。所以我想我必须添加我想使用的evry Play API的对象的定义。我对吗 ? –

回答

5

下面是一个简单的应用程序,演示如何使用Frege with 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())) 
     ); 
    } 
} 

这里我们定义了相应的请求和响应和JSON转换为那些FromJSON和2种类型ToJSON输入类实例。 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都来自游戏的框架,所以我们必须添加本地绑定弗雷格提其纯度或可能的空值等,这是一件好事,因为弗雷格是一种纯粹的语言,并没有null的概念,我们必须明确提及可能的副作用或Maybe编译器的空值与Scala不同,您可以调用任何Java方法。

所效力的弗雷格本地绑定:

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,可以用来编译弗雷格源的播放项目。如果有人想尝试一下,我已经在Github推这个示例应用程序。

+0

伟大的工作,一如既往,Marimuthu!不过,我有一个问题:为什么我们不能说'request.body.asText'而不是'toJson.toString'? – Ingo

+0

Okey似乎可以工作,但我认为这是一个棘手的问题...我想用这个工作和一个认真的项目,我在这里放松一些自动化功能,像JSON解析和数据库管理那样购买这个播放框架。但我不介意一些个人项目,等待播放端口免费 –

+0

Thanks Ingo!我首先尝试了它,但它似乎不适用于JSON请求。 –