{"id":13774021,"url":"https://github.com/extism/haskell-sdk","last_synced_at":"2025-07-06T17:33:15.297Z","repository":{"id":194880053,"uuid":"691370651","full_name":"extism/haskell-sdk","owner":"extism","description":"Extism Haskell Host SDK - easily run WebAssembly modules / plugins from Haskell applications","archived":false,"fork":false,"pushed_at":"2024-12-03T22:53:51.000Z","size":2697,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-23T08:41:59.767Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://extism.org","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/extism.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-14T03:35:01.000Z","updated_at":"2025-03-20T18:18:41.000Z","dependencies_parsed_at":"2023-10-24T20:32:08.342Z","dependency_job_id":"d5533e4d-a519-4201-8511-cd4f2d00f4ae","html_url":"https://github.com/extism/haskell-sdk","commit_stats":null,"previous_names":["extism/haskell-sdk"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extism%2Fhaskell-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extism%2Fhaskell-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extism%2Fhaskell-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extism%2Fhaskell-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/extism","download_url":"https://codeload.github.com/extism/haskell-sdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247796294,"owners_count":20997545,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T17:01:22.956Z","updated_at":"2025-04-08T07:32:20.184Z","avatar_url":"https://github.com/extism.png","language":"Haskell","readme":"# Extism Haskell Host SDK\n\nThis repo contains the Haskell package for integrating with the [Extism](https://extism.org/) runtime.\n\n\u003e **Note**: If you're unsure what Extism is or what an SDK is see our homepage: [https://extism.org](https://extism.org).\n\n## Documentation\n\nDocumentation is available at [https://hackage.haskell.org/package/extism](https://hackage.haskell.org/package/extism)\n\n## Installation\n\n### Install the Extism Runtime Dependency\n\nFor this library, you first need to install the Extism Runtime. You can [download the shared object directly from a release](https://github.com/extism/extism/releases) or use the [Extism CLI](https://github.com/extism/cli) to install it.\n\n### Add the library to dune\n\nThen add `extism` to your [cabal](https://www.haskell.org/cabal/) file:\n\n```\nlibrary\n  build-depends: extism\n```\n\n## Getting Started\n\nThis guide should walk you through some of the concepts in Extism and the Haskell bindings.\n\n### Creating A Plug-in\n\nThe primary concept in Extism is the [plug-in](https://extism.org/docs/concepts/plug-in). You can think of a plug-in as a code module stored in a `.wasm` file.\n\nSince you may not have an Extism plug-in on hand to test, let's load a demo plug-in from the web:\n\n```haskell\nmodule Main where\nimport Extism\n\nmain = do\n  plugin \u003c- unwrap \u003c$\u003e newPlugin (manifest [wasm]) [] True\n  res \u003c- unwrap \u003c$\u003e call plugin \"count_vowels\" \"Hello, world!\"\n  putStrLn res\n  where\n    wasm = wasmURL \"GET\" \"https://github.com/extism/plugins/releases/latest/download/count_vowels.wasm\"\n\n-- Prints: {\"count\":3,\"total\":3,\"vowels\":\"aeiouAEIOU\"}\"\n```\n\n\u003e **Note**: See [the Manifest docs](https://hackage.haskell.org/package/extism-manifest) as it has a rich schema and a lot of options.\n\nThis plug-in was written in Rust and it does one thing, it counts vowels in a string. As such, it exposes one \"export\" function: `count_vowels`. We can call exports using [Extism.call](https://hackage.haskell.org/package/extism/docs/Extism.html#v:call):\n\nAll exports have a simple interface of bytes-in and bytes-out. This plug-in happens to take a string and return a JSON encoded string with a report of results.\n\nThis library also allowes for conversion of input/outputs types using [FromBytes](https://hackage.haskell.org/package/extism/docs/Extism.html#t:FromBytes) and [ToBytes](https://hackage.haskell.org/package/extism/docs/Extism.html#t:ToBytes)\n\n### Plug-in State\n\nPlug-ins may be stateful or stateless. Plug-ins can maintain state b/w calls by the use of variables. Our count vowels plug-in remembers the total number of vowels it's ever counted in the \"total\" key in the result. You can see this by making subsequent calls to the export:\n\n```haskell\nghci\u003e unwrap \u003c$\u003e call plugin \"count_vowels\" \"Hello, world!\"\n{\"count\":3,\"total\":9,\"vowels\":\"aeiouAEIOU\"}\nghci\u003e unwrap \u003c$\u003e call plugin \"count_vowels\" \"Hello, world!\"\n{\"count\":3,\"total\":12,\"vowels\":\"aeiouAEIOU\"}\n```\n\nThese variables will persist until this plug-in is freed or you initialize a new one.\n\n### Configuration\n\nPlug-ins may optionally take a configuration object. This is a static way to configure the plug-in. Our count-vowels plugin takes an optional configuration to change out which characters are considered vowels. Example:\n\n```haskell\nghci\u003e let manifest = manifest [wasm]\nghci\u003e plugin \u003c- unwrap \u003c$\u003e newPlugin manifest [] True\nghci\u003e res \u003c- (unwrap \u003c$\u003e call plugin \"count_vowels\" \"Yellow, world!\" :: String)\nghci\u003e res\n{\"count\":3,\"total\":3,\"vowels\":\"aeiouAEIOU\"}\n\nghci\u003e plugin \u003c- withConfig (manifest [wasm]) [(\"vowels\",\"aeiouyAEIOUY\")] ;;\nghci\u003e res \u003c- (unwrap \u003c$\u003e call plugin \"count_vowels\" \"Yellow, world!\" :: String)\nghci\u003e res\n{\"count\":4,\"total\":4,\"vowels\":\"aeiouAEIOUY\"}\n```\n\n### Host Functions\n\nLet's extend our count-vowels example a little bit: we can intercept the results and adjust them before returning from the plugin using a `hello_world` [host function](https://extism.org/docs/concepts/host-functions)\nwith `wasm/code-functions.wasm`\n\n[Host functions](https://extism.org/docs/concepts/host-functions) allow us to grant new capabilities to our plug-ins from our application. They are simply some OCaml functions you write which can be passed down and invoked from any language inside the plug-in.\n\nUsing [Extism.HostFunction.hostFunction](https://hackage.haskell.org/package/extism/docs/Extism-HostFunction.html#v:hostFunction) we can define a host function that can be called from the guest plug-in.\n\nIn this example, we want to expose a single function to our plugin (in Haskell types): `hello_world :: String -\u003e String` which will intercept the original result and replace it with a new one.\n\nLet's load the manifest like usual but load up `wasm/code-functions.wasm` plug-in:\n\n```haskell\n{-# LANGUAGE DeriveDataTypeable #-}\n\nmodule Main where\n\nimport Extism\nimport Extism.HostFunction\nimport Extism.JSON\nimport Extism.Manifest (manifest, wasmFile)\n\nnewtype Count = Count {count :: Int} deriving (Data, Show)\n\nhello currPlugin msg = do\n  putStrLn . unwrap \u003c$\u003e input currPlugin 0\n  putStrLn \"Hello from Haskell!\"\n  putStrLn msg\n  output currPlugin 0 (JSON $ Count 999)\n\nmain = do\n  setLogFile \"stdout\" LogError\n  f \u003c- newFunction \"hello_world\" [ptr] [ptr] \"Hello, again\" hello\n  plugin \u003c- unwrap \u003c$\u003e newPlugin m [f] True\n  id \u003c- pluginID plugin\n  print id\n  JSON res \u003c- (unwrap \u003c$\u003e call plugin \"count_vowels\" \"this is a test\" :: IO (JSON Count))\n  print res\n  where\n    m = manifest [wasmFile \"wasm/code-functions.wasm\"]\n-- Prints: Count {count = 999}\n```\n\n\u003e *Note*: In order to write host functions you should get familiar with the methods on the [Extism.HostFunction](https://hackage.haskell.org/package/extism/docs/Extism-HostFunction.html) module.\n","funding_links":[],"categories":["\u003ca name=\"extism\"\u003e\u003c/a\u003e[Extism](https://github.com/extism/extism) \u003csup\u003e[top⇈](#contents)\u003c/sup\u003e"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fextism%2Fhaskell-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fextism%2Fhaskell-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fextism%2Fhaskell-sdk/lists"}