foreign-function-interface.lagda.rst 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. ..
  2. ::
  3. module language.foreign-function-interface where
  4. open import Agda.Primitive
  5. open import Agda.Builtin.Bool
  6. postulate <Name> : Set
  7. .. _foreign-function-interface:
  8. **************************
  9. Foreign Function Interface
  10. **************************
  11. .. contents::
  12. :depth: 2
  13. :local:
  14. Compiler Pragmas
  15. ================
  16. There are two backend-generic pragmas used for the FFI::
  17. {-# COMPILE <Backend> <Name> <Text> #-}
  18. {-# FOREIGN <Backend> <Text> #-}
  19. The ``COMPILE`` pragma associates some information ``<Text>`` with a
  20. name ``<Name>`` defined in the same module, and the ``FOREIGN`` pragma
  21. associates ``<Text>`` with the current top-level module. This
  22. information is interpreted by the specific backend during compilation
  23. (see below). These pragmas were added in Agda 2.5.3.
  24. Haskell FFI
  25. ===========
  26. .. note::
  27. This section applies to the :ref:`ghc-backend`.
  28. The ``FOREIGN`` pragma
  29. ----------------------
  30. The GHC backend interprets ``FOREIGN`` pragmas as inline Haskell code and can
  31. contain arbitrary code (including import statements) that will be added to the
  32. compiled module. For instance::
  33. {-# FOREIGN GHC import Data.Maybe #-}
  34. {-# FOREIGN GHC
  35. data Foo = Foo | Bar Foo
  36. countBars :: Foo -> Integer
  37. countBars Foo = 0
  38. countBars (Bar f) = 1 + countBars f
  39. #-}
  40. The ``COMPILE`` pragma
  41. ----------------------
  42. There are four forms of ``COMPILE`` annotations recognized by the GHC backend
  43. .. code-block:: agda
  44. {-# COMPILE GHC <Name> = <HaskellCode> #-}
  45. {-# COMPILE GHC <Name> = type <HaskellType> #-}
  46. {-# COMPILE GHC <Name> = data <HaskellData> (<HsCon1> | .. | <HsConN>) #-}
  47. {-# COMPILE GHC <Name> as <HaskellName> #-}
  48. The first three tells the compiler how to compile a given Agda definition and the last
  49. exposes an Agda definition under a particular Haskell name allowing Agda libraries to
  50. be used from Haskell.
  51. .. _compiled_type_pragma:
  52. Using Haskell Types from Agda
  53. -----------------------------
  54. In order to use a Haskell function from Agda its type must be mapped to an Agda
  55. type. This mapping can be configured using the ``type`` and ``data`` forms of the
  56. ``COMPILE`` pragma.
  57. Opaque types
  58. ^^^^^^^^^^^^
  59. Opaque Haskell types are exposed to Agda by postulating an Agda type and
  60. associating it to the Haskell type using the ``type`` form of the ``COMPILE``
  61. pragma::
  62. {-# FOREIGN GHC import qualified System.IO #-}
  63. postulate FileHandle : Set
  64. {-# COMPILE GHC FileHandle = type System.IO.Handle #-}
  65. This tells the compiler that the Agda type ``FileHandle`` corresponds to the Haskell
  66. type ``System.IO.Handle`` and will enable functions using file handles to be used
  67. from Agda.
  68. Data types
  69. ^^^^^^^^^^
  70. Non-opaque Haskell data types can be mapped to Agda datatypes using the ``data`` form
  71. of the ``COMPILED`` pragma::
  72. data Maybe (A : Set) : Set where
  73. nothing : Maybe A
  74. just : A → Maybe A
  75. {-# COMPILE GHC Maybe = data Maybe (Nothing | Just) #-}
  76. The compiler checks that the types of the Agda constructors match the types of the
  77. corresponding Haskell constructors and that no constructors have been left out
  78. (on either side).
  79. Built-in Types
  80. ^^^^^^^^^^^^^^
  81. The GHC backend compiles certain Agda :ref:`built-in types <built-ins>` to
  82. special Haskell types. The mapping between Agda built-in types and Haskell
  83. types is as follows:
  84. ============= ==================
  85. Agda Built-in Haskell Type
  86. ============= ==================
  87. ``NAT`` ``Integer``
  88. ``INTEGER`` ``Integer``
  89. ``STRING`` ``Data.Text.Text``
  90. ``CHAR`` ``Char``
  91. ``BOOL`` ``Bool``
  92. ``FLOAT`` ``Double``
  93. ============= ==================
  94. .. warning::
  95. Haskell code manipulating Agda natural numbers as integers must take
  96. care to avoid negative values.
  97. .. warning::
  98. Agda ``FLOAT`` values have only one logical ``NaN`` value. At runtime,
  99. there might be multiple different ``NaN`` representations present. All
  100. such ``NaN`` values must be treated equal by FFI calls.
  101. .. _compiled_pragma:
  102. Using Haskell functions from Agda
  103. ---------------------------------
  104. Once a suitable mapping between Haskell types and Agda types has been set
  105. up, Haskell functions whose types map to Agda types can be exposed to Agda
  106. code with a ``COMPILE`` pragma::
  107. open import Agda.Builtin.IO
  108. open import Agda.Builtin.String
  109. open import Agda.Builtin.Unit
  110. {-# FOREIGN GHC
  111. import qualified Data.Text.IO as Text
  112. import qualified System.IO as IO
  113. #-}
  114. postulate
  115. stdout : FileHandle
  116. hPutStrLn : FileHandle → String → IO ⊤
  117. {-# COMPILE GHC stdout = IO.stdout #-}
  118. {-# COMPILE GHC hPutStrLn = Text.hPutStrLn #-}
  119. The compiler checks that the type of the given Haskell code matches the
  120. type of the Agda function. Note that the ``COMPILE`` pragma only affects
  121. the runtime behaviour--at type-checking time the functions are treated as
  122. postulates.
  123. .. warning::
  124. It is possible to give Haskell definitions to defined (non-postulate)
  125. Agda functions. In this case the Agda definition will be used at
  126. type-checking time and the Haskell definition at runtime. However, there
  127. are no checks to ensure that the Agda code and the Haskell code behave
  128. the same and **discrepancies may lead to undefined behaviour**.
  129. This feature can be used to let you reason about code involving calls to
  130. Haskell functions under the assumption that you have a correct Agda model
  131. of the behaviour of the Haskell code.
  132. Using Agda functions from Haskell
  133. ---------------------------------
  134. Since Agda 2.3.4 Agda functions can be exposed to Haskell code using
  135. the ``as`` form of the ``COMPILE`` pragma::
  136. module IdAgda where
  137. idAgda : ∀ {A : Set} → A → A
  138. idAgda x = x
  139. {-# COMPILE GHC idAgda as idAgdaFromHs #-}
  140. This tells the compiler that the Agda function ``idAgda`` should be compiled
  141. to a Haskell function called ``idAgdaFromHs``. Without this pragma, functions
  142. are compiled to Haskell functions with unpredictable names and, as a result,
  143. cannot be invoked from Haskell. The type of ``idAgdaFromHs`` will be the translated
  144. type of ``idAgda``.
  145. The compiled and exported function ``idAgdaFromHs`` can then be imported and
  146. invoked from Haskell like this:
  147. .. code-block:: haskell
  148. -- file UseIdAgda.hs
  149. module UseIdAgda where
  150. import MAlonzo.Code.IdAgda (idAgdaFromHs)
  151. -- idAgdaFromHs :: () -> a -> a
  152. idAgdaApplied :: a -> a
  153. idAgdaApplied = idAgdaFromHs ()
  154. Polymorphic functions
  155. ---------------------
  156. Agda is a monomorphic language, so polymorphic functions are modeled
  157. as functions taking types as arguments. These arguments will be
  158. present in the compiled code as well, so when calling polymorphic
  159. Haskell functions they have to be discarded explicitly. For instance,
  160. ::
  161. postulate
  162. ioReturn : {A : Set} → A → IO A
  163. {-# COMPILE GHC ioReturn = \ _ x -> return x #-}
  164. In this case compiled calls to ``ioReturn`` will still have ``A`` as an
  165. argument, so the compiled definition ignores its first argument
  166. and then calls the polymorphic Haskell ``return`` function.
  167. Level-polymorphic types
  168. -----------------------
  169. :ref:`Level-polymorphic types <universe-levels>` face a similar problem to
  170. polymorphic functions. Since Haskell does not have universe levels the Agda
  171. type will have more arguments than the corresponding Haskell type. This can be solved
  172. by defining a Haskell type synonym with the appropriate number of phantom
  173. arguments. For instance:
  174. ::
  175. data Either {a b} (A : Set a) (B : Set b) : Set (a ⊔ b) where
  176. left : A → Either A B
  177. right : B → Either A B
  178. {-# FOREIGN GHC type AgdaEither a b = Either #-}
  179. {-# COMPILE GHC Either = data AgdaEither (Left | Right) #-}
  180. Handling typeclass constraints
  181. ------------------------------
  182. There is (currently) no way to map a Haskell type with type class constraints to an
  183. Agda type. This means that functions with class constraints cannot be used from Agda.
  184. However, this can be worked around by wrapping class constraints in Haskell data types,
  185. and providing Haskell functions using explicit dictionary passing.
  186. For instance, suppose we have a simple GUI library in Haskell:
  187. .. code-block:: haskell
  188. module GUILib where
  189. class Widget w
  190. setVisible :: Widget w => w -> Bool -> IO ()
  191. data Window
  192. instance Widget Window
  193. newWindow :: IO Window
  194. To use this library from Agda we first define a Haskell type for widget dictionaries and map this
  195. to an Agda type ``Widget``::
  196. {-# FOREIGN GHC import GUILib #-}
  197. {-# FOREIGN GHC data WidgetDict w = Widget w => WidgetDict #-}
  198. postulate
  199. Widget : Set → Set
  200. {-# COMPILE GHC Widget = type WidgetDict #-}
  201. We can then expose ``setVisible`` as an Agda function taking a Widget
  202. :ref:`instance argument <instance-arguments>`::
  203. postulate
  204. setVisible : {w : Set} {{_ : Widget w}} → w → Bool → IO ⊤
  205. {-# COMPILE GHC setVisible = \ _ WidgetDict -> setVisible #-}
  206. Note that the Agda ``Widget`` argument corresponds to a ``WidgetDict`` argument
  207. on the Haskell side. When we match on the ``WidgetDict`` constructor in the Haskell
  208. code, the packed up dictionary will become available for the call to ``setVisible``.
  209. The window type and functions are mapped as expected and we also add an Agda instance
  210. packing up the ``Widget Window`` Haskell instance into a ``WidgetDict``::
  211. postulate
  212. Window : Set
  213. newWindow : IO Window
  214. instance WidgetWindow : Widget Window
  215. {-# COMPILE GHC Window = type Window #-}
  216. {-# COMPILE GHC newWindow = newWindow #-}
  217. {-# COMPILE GHC WidgetWindow = WidgetDict #-}
  218. ..
  219. ::
  220. infixr 1 _>>=_
  221. postulate
  222. return : {A : Set} → A → IO A
  223. _>>=_ : {A B : Set} → IO A → (A → IO B) → IO B
  224. {-# COMPILE GHC return = \ _ -> return #-}
  225. {-# COMPILE GHC _>>=_ = \ _ _ -> (>>=) #-}
  226. We can then write code like this::
  227. openWindow : IO Window
  228. openWindow = newWindow >>= λ w →
  229. setVisible w true >>= λ _ →
  230. return w
  231. JavaScript FFI
  232. ==============
  233. The :ref:`JavaScript backend <javascript-backend>` recognizes ``COMPILE`` pragmas of the following form::
  234. {-# COMPILE JS <Name> = <JsCode> #-}
  235. where ``<Name>`` is a postulate, constructor, or data type. The code for a data type is used to compile
  236. pattern matching and should be a function taking a value of the data type and a table of functions
  237. (corresponding to case branches) indexed by the constructor names. For instance, this is the compiled
  238. code for the ``List`` type, compiling lists to JavaScript arrays::
  239. data List {a} (A : Set a) : Set a where
  240. [] : List A
  241. _∷_ : (x : A) (xs : List A) → List A
  242. {-# COMPILE JS List = function(x,v) {
  243. if (x.length < 1) {
  244. return v["[]"]();
  245. } else {
  246. return v["_∷_"](x[0], x.slice(1));
  247. }
  248. } #-}
  249. {-# COMPILE JS [] = Array() #-}
  250. {-# COMPILE JS _∷_ = function (x) { return function(y) { return Array(x).concat(y); }; } #-}