具有类型同义词的函数

Function with type synonym

很抱歉问了一个可能很愚蠢的问题,但是回到 Haskell 做一些从一个数据库包到另一个数据库包的转换,我发现自己对如何正确地做到这一点有点困惑。

Database.SQLite3模块中,有一个execWithCallback类型为

execWithCallback :: Database -> Text -> ExecCallback -> IO ()

现在,回调定义为

type ExecCallback = ColumnCount -> [Text]-> [Maybe Text] -> IO ()

即类型为ExecCallback的函数 我愚蠢的测试代码编译并正确运行:

{-# LANGUAGE OverloadedStrings #-}

import Database.SQLite3
import Data.Text

cb :: ColumnCount -> [Text] -> [Maybe Text] -> IO ()
cb  n cnl ct = do print $ cnl !! 1
                  return ()

main = do
  dh <- open "fileinfo.sqlite"
  execWithCallback dh "select * from files;" cb
  close dh

但是,类型的意义何在???而且,我如何指定 cbExecCallback??

在 Haskell 中,您使用 type 定义了一个 类型的同义词 。在您的示例中,这意味着 ExecCallback 只是类型 ColumnCount -> [Text]-> [Maybe Text] -> IO () 的别名,它们可以互换。

您可以更改以下行

cb :: ColumnCount -> [Text] -> [Maybe Text] -> IO ()
cb  n cnl ct = do print $ cnl !! 1
                  return ()

cb :: ExecCallback
cb  n cnl ct = do print $ cnl !! 1
                  return ()

一切都会照原样工作。它可以使您的代码更短、更易读。

另一个很好的例子是

type String = [Char]

in Prelude。我敢打赌,在大多数情况下,您通常使用 String 而不是 [Char]。但您完全可以自由使用。

另一个(完全不相关的)例子是 conduit package where some type synonyms 有很大的不同:

type Sink i = ConduitM i Void
type Consumer i m r = forall o. ConduitM i o m r

对于任何类型值的接收器 iSink i 似乎比 ConduitM i Void 更具可读性。 Consumer.

相同