绑定链中更平滑的类型注释

for*_*ker 4 haskell

所以我有这个工作示例(Snap + Postgres):

listBooks :: AppHandler ()
listBooks = do
  results <- query_ "select * from books"
  writeJSON $ (results :: [Book])
Run Code Online (Sandbox Code Playgroud)

作为练习,我试图用>>=操作符重写它,但注释类型的需要杀死了美学.我想不出更好的东西:

query_ "select * from books" >>= return.(\x -> x :: [Book]) >>= writeJSON
Run Code Online (Sandbox Code Playgroud)

还有其他"更顺畅"的方式吗?(最好不指定包装单子类型)

Ørj*_*sen 7

你可以稍微缩短一下

query_ "select * from books" >>= writeJSON . (\x -> x :: [Book])
Run Code Online (Sandbox Code Playgroud)

除此之外,还没有,尽管有计划为快捷语法实现GHC扩展

(:: [Book]) = (\x -> x :: [Book])
Run Code Online (Sandbox Code Playgroud)

看看@ duplode的链接 ,好像它的代码开始写入3天前,所以应该在下一个GHC版本中.


Dan*_*ner 5

如果你打开PartialTypeSignatures,你可以写:

query_ "select * from books" >>= (writeJSON :: [Book] -> _)
Run Code Online (Sandbox Code Playgroud)

人们也可以将此作为约束query_; 例如,在您的do版本中,它将是:

listBooks :: AppHandler ()
listBooks = do
  results <- query_ "select * from books" :: _ [Book]
  writeJSON results
Run Code Online (Sandbox Code Playgroud)

在GHC的未来版本中,还将有可见的类型应用程序.假设writeJSONquery_具有合适的类型声明,您就可以编写以下其中一个:

query_ @[Book] "select * from books" >>= writeJSON
query_ "select * from books" >>= writeJSON @[Book]
Run Code Online (Sandbox Code Playgroud)

最后,如果您反对输入注释,但可以使用术语注释,那么您可以编写

query_ "select * from books" >>= asAppliedTo [Book{}] writeJSON
Run Code Online (Sandbox Code Playgroud)

哪个Book是该Book类型的假设构造函数(重点是[Book{}],虽然是无意义的值,但是具有单态类型).我似乎记得这asAppliedTo是一个标准的事情,但快速的hoogle并没有透露它; 无论如何,它的实现类似于:

asAppliedTo :: arg -> (arg -> result) -> (arg -> result)
asAppliedTo _ = id
Run Code Online (Sandbox Code Playgroud)