TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Calling Haskell from Swift

91 pointsby romesabout 1 year ago

9 comments

wk_endabout 1 year ago
This is pretty cool. In FP there&#x27;s a pattern called &quot;functional core, imperative shell&quot; [0]; here, you can build your &quot;functional core&quot; in Haskell and your imperative shell in a language which - depending on your preferences, some might say - is a little more suitable for building an imperative shell. Because it uses JSON as the &quot;wire format&quot; between the two languages, you can then easily build out a different imperative shell for whichever platforms you want to support.<p>[0] <a href="https:&#x2F;&#x2F;www.destroyallsoftware.com&#x2F;screencasts&#x2F;catalog&#x2F;functional-core-imperative-shell" rel="nofollow">https:&#x2F;&#x2F;www.destroyallsoftware.com&#x2F;screencasts&#x2F;catalog&#x2F;funct...</a>
bradrnabout 1 year ago
I’ve done something like this before to call Haskell from C++ (in [0]), so that I could build my GUI using Qt. It worked pretty well, except that I ran into various difficult-to-resolve linking problems on both Windows and Linux. After a year or two of trying to maintain it, I gave up and switched to a protocol where both sides pass JSON over stdin&#x2F;stdout. This particular piece of software doesn’t require a huge amount of communication or shared data, so it works well enough.<p>The really nice thing about the original interop code, though, is that GHC’s new WASM backend uses essentially the same foreign function interface to export functions to JavaScript. So with only some minor modifications, I was able to get the same program working on a webpage [1], which I think is pretty cool.<p>[0] <a href="https:&#x2F;&#x2F;github.com&#x2F;bradrn&#x2F;brassica">https:&#x2F;&#x2F;github.com&#x2F;bradrn&#x2F;brassica</a>, and see in particular the old version of <a href="https:&#x2F;&#x2F;github.com&#x2F;bradrn&#x2F;brassica&#x2F;blob&#x2F;93d4353c5736018ec0944433d044ce6c4dc3ba3b&#x2F;ARCHITECTURE.md">https:&#x2F;&#x2F;github.com&#x2F;bradrn&#x2F;brassica&#x2F;blob&#x2F;93d4353c5736018ec094...</a><p>[1] At the risk of DDOS’ing my poor little home server: <a href="https:&#x2F;&#x2F;bradrn.com&#x2F;brassica&#x2F;" rel="nofollow">https:&#x2F;&#x2F;bradrn.com&#x2F;brassica&#x2F;</a>
Bogdanpabout 1 year ago
I&#x27;ve been doing similar things with Swift and Racket:<p>* <a href="https:&#x2F;&#x2F;defn.io&#x2F;2023&#x2F;03&#x2F;19&#x2F;racketfest-talk-2023&#x2F;" rel="nofollow">https:&#x2F;&#x2F;defn.io&#x2F;2023&#x2F;03&#x2F;19&#x2F;racketfest-talk-2023&#x2F;</a><p>* <a href="https:&#x2F;&#x2F;defn.io&#x2F;2023&#x2F;02&#x2F;04&#x2F;racket-foreign-callouts-to-swift&#x2F;" rel="nofollow">https:&#x2F;&#x2F;defn.io&#x2F;2023&#x2F;02&#x2F;04&#x2F;racket-foreign-callouts-to-swift&#x2F;</a><p>I also started out using JSON to exchange data between the languages, but eventually wiring everything manually became an annoyance so I came up with a little Racket DSL[1] that automatically serializes and deserializes between the two languages (at runtime in Racket &amp; using code generation in Swift). So far, I&#x27;ve built two apps with this approach, and I think it&#x27;s great:<p>* <a href="https:&#x2F;&#x2F;github.com&#x2F;Bogdanp&#x2F;Franz">https:&#x2F;&#x2F;github.com&#x2F;Bogdanp&#x2F;Franz</a> (macOS, Windows, Linux)<p>* <a href="https:&#x2F;&#x2F;github.com&#x2F;Bogdanp&#x2F;remember">https:&#x2F;&#x2F;github.com&#x2F;Bogdanp&#x2F;remember</a> (macOS, iOS)<p>[1]: <a href="https:&#x2F;&#x2F;github.com&#x2F;bogdanp&#x2F;noise">https:&#x2F;&#x2F;github.com&#x2F;bogdanp&#x2F;noise</a>
saagarjhaabout 1 year ago
There&#x27;s really no need to make an unsafe temporary allocation for a simple type like Int. You can just assign it a value, and if you only need it once, just pass it through with &amp;. For example:<p><pre><code> var size = buf_size c_birthday(rawPtr.baseAddress, data_len, res_ptr.baseAddress, &amp;size) </code></pre> In this case, since you know your size is fixed, and it&#x27;s actually quite large (1 MB) it is never going to fit on the stack anyways. So there is no need to use a function that will try to do that: just use Array&#x27;s init(unsafeUninitializedCapacity:initializingWith:) initializer instead, and you will bridge it into Swift&#x27;s lifetime management without having to do the whole closure dance. Finally, since your API is unlikely to modify the buffer you pass it in, try using withUnsafeBytes instead of withUnsafeMutableBytes (and correctly annotating the pointer with const in your bridge).
评论 #39915737 未加载
w10-1about 1 year ago
The article doesn&#x27;t really explain the approach taken, to serialize data at the function call boundary.<p>Haskell supports a C API&#x2F;ABI directly, as does Swift. E.g., Swift String can be shared as cstring, i.e., a null-terminated byte array, with no allocations needed. Since both languages support the (per-platform) C API&#x2F;ABI, that would seem to be the best option, with home-grown serialization a risk (or perhaps a fallback where necessary).<p>In most cases, Swift simply handles the C-type without needing any special bridging. In some cases of ambiguity, you can add attributes on the C declarations to tell the Swift compiler how to handle the data and call.<p>Haskell also supports a range of C-ABI annotations, but that&#x27;s on the Haskell language side, likely invisible to Swift.<p>A super-helpful contribution would be to see what range of types bridge without annotations and what additional types can be handled with annotations.<p>But since the author did go to all the effort of marshaling, they must have discovered unavoidable limitations. It would be most helpful to know what those were!<p>Edit: here&#x27;s a tutorial for swift calling Haskell from 5 years ago, before the huge changes in Swift 5.9 for C&#x2F;C++ interoperability:<p><a href="https:&#x2F;&#x2F;github.com&#x2F;nanotech&#x2F;swift-haskell-tutorial&#x2F;">https:&#x2F;&#x2F;github.com&#x2F;nanotech&#x2F;swift-haskell-tutorial&#x2F;</a>
arulpugazhabout 1 year ago
The blog is so neat and pretty!
bsaulabout 1 year ago
That’s nice, except for swift’s abysmal json encoding &#x2F; decoding performance.
评论 #39911820 未加载
frizlababout 1 year ago
I always flinch when I see Xcode written with a capital C!<p>The post is interesting otherwise.
评论 #39911227 未加载
veryrealsidabout 1 year ago
My CS professor would be proud