r/fsharp

▲ 8 r/fsharp

Is it important to know how memory works to fully understand f#?

So I work on a e-commerce marketplace and after realizing doing complex rules and validation in typescript is hell on earth I looked for another solution and I stumbled upon f# which was perfect. We use it mainly as a domain server where a domain in the system is getting too complexed.

I’m the only person that can work on this and I want to teach a couple of my coworkers f# but they have no idea how memory works not even stacks and heaps, and with a language like f# I feel like you can’t really get away with not knowing how it works like typescript

So I was wondering do you think f# is one of those languages you can learn without fully understanding how memory works

reddit.com
u/Montrell1223 — 2 days ago
▲ 23 r/fsharp

I've recently started learning F# and the entire paradigm of functional programming. I'm doing this because I want to research the applications of both the language and the approach it requires in gamedev, particularly in systems like finite state machines and ECS. Are there any, and could you point me to any good sources?

reddit.com
u/AnnoyingMemer — 8 days ago
▲ 16 r/fsharp

Decoding the Indus Valley script with F# — 16 Alloy assertions, SqlHydra-typed read path, dotnet fsi reproducibility

I just published a paper using F# end-to-end to test a hypothesis about the Indus Valley script (the writing system from the Harappan civilization, ~2600–1900 BCE, still undeciphered).

GitHub: https://github.com/chanakyan/ledger-of-meluhha

License: BSD-2-Clause (human use), AI use prohibited

The hypothesis: the script is not a phonetic language. It's a five-field cargo-tag system encoding merchant, commodity, weight tier, quantity, and route — essentially Bronze Age barcodes for goods moving Lothal → Dilmun → Ur.

The F# stack:

Verification before implementation. Sixteen Alloy 6 assertions written first against the schema. All UNSAT at scope 6. SQL was written only after the schema was machine-verified consistent. The Alloy → F# bridge lives in lib/alloy-fsx/, which also includes an AlsParser.fs (recursive descent + Pratt expression parser) that parses 37/116 of the AlloyTools model zoo.

Read path vs write path separation. Raw SQL is permitted only in *_to_sqlite.fsx scripts (the ingest write path). The read path uses SqlHydra-generated typed queries in hydra/IndusCorpusQueries.fs. A pre-commit hook enforces this — raw SQL in non-ingest files fails commit. This means once data is in SQLite, every query is type-checked at compile time, no ad-hoc strings.

Discriminated unions as S-expressions. The paper, the website, the SQL ingest, and the SMT proofs are all generated from a shared F# DU tree. Knuth's WEB insight generalized: code and documentation are one artifact viewed N ways. The viewing function is a fold over the DU. F# DUs already are S-expressions; the type system is the structure; pattern matching is the evaluator. No separate S-expression parser needed.

Reproducibility on dotnet fsi.

git clone https://github.com/chanakyan/ledger-of-meluhha

cd ledger-of-meluhha

dotnet fsi indus_decoder.fsx

And get the same decode results as the paper. No proprietary toolchain. The 10-minute verification protocol in the paper's "For Journalists" section is meant for non-programmers — but for F# folks it's faster than 10 minutes.

The decode itself. Two Mohenjo-daro seals (M-52A and M-148A) end-to-end through the codebook. Mass decode across 179 inscriptions: 65% commodity assignment, 21% route assignment. Sign 342 (jar motif) dominates the corpus at ~10% — anomalous for a phoneme, expected for a commodity class.

Why F# specifically. I tried Python first. The strings-everywhere problem killed correctness — silent typos in sign IDs produced plausible-looking garbage decodes. F# DUs made invalid states unrepresentable. The compiler caught dozens of bugs Python had let through.

The paper is in ledger_of_meluhha.tex (3,657 lines, ~150 KB). The corpus databases are in indus_corpus.db, indus_codebook.db, indus_lssc.db. The decoders are seven .fsx files at the repo root.

Happy to answer questions about the typed-records pattern, the Alloy-to-F# generation, SqlHydra integration, or the F# DU → multi-target weave architecture. The cross-domain stuff (the Bronze Age trade history) is in the paper for those interested.

reddit.com
u/chanakya_ — 2 days ago
▲ 21 r/fsharp

Hey Everyone,

Thought I'd share the Omni Blade on sale for just 0.99$ until the 13th.

The game was made fully in F# on the FOSS F# Engine Nu by the community legend - Bryan its his passion project.

If for whatever reason you wanted to try it but couldn't justify the purchase now's the time!

Disclosure:

I am not affiliated/paid by Bryan but I'm his fan :)

itch.io
u/asieradzk — 6 days ago
▲ 6 r/fsharp

I might be going a bit all over the place, but I appreciate anyone reading and offering input.

I'm working on a side project that is an FSharp SAFE stack application. One of the issues that I've been running into is the multiple was of doing things, so I started out with some Saturn configuration, Fable.Remoting, and Giraffe endpoints and since I've upgraded to dotnet 10, I've eventually gotten rid of the Saturn components and almost exclusively am using Giraffe with dotnet EndpointRoutes so that I can better do things like e-tags and whatnot. Is this normal?

But my main example is on the data access layer. I found that there were a lot of cool looking libraries and after playing around a bit, I decided that I like Dapper, Dapper.FSharp, and DbFun.

DbFun does some cool stuff and looks like a more type safe Dapper with build or test run time evaluation of your queries, so a bad query or a typo will fail to build. It looks a bit like this (with explicit typing):

```fsharp
let findByUserId (userId: UserId) (queryBuilder: QueryBuilder) : (IConnector<unit> -> Async<UserOption>)->
queryBuilder.Sql<UserId, User option>(someSql, "id") userId
```

This is pretty cool. The but though is that the new http handlers don't take an `Async`, they take a `Task`. It would be cool if it was possible to get the query object generated, but DbFun appears to be all partially applied functions, so I can't put it through a runner that returns a `Task`.

Now, I can convert the Async to a Task, but I'd prefer not to switch between the two. I ran some tests between DbFun with Async converted to Task and Dapper and there was a difference in memory and execution time. It's not a huge deal and this is a side project, but I'd prefer to stick with one type up through the stack.

This currently leaves me with using Dapper and the typical Repository pattern, though even this repo is getting bloated already.

What I'm doing at the moment until I decide a direction is I'm creating the DbFun queries for testing and type safety stuff, but also putting those queries into my dapper commands wrapped with instrumentation:

```fsharp
// I'm pretty sure I can make some handlers for dapper to work with my single case DUs, but I'm still looking at the best way to do strong typing of IDs.
member this.FindTask(id:IdentityId, mediaId: MediaId, ct: CancellationToken) : Task<SomeFindResponseType option> =
let instrument = withDbActivity logger (nameof(findByUserIdAndMediaIdQuery)) (Some findByUserIdAndMediaIdSql)
instrument(fun () -> task {
let conn = connectionFactory()
let mediaGuid: Guid = mediaId
let guidValue = match id with | IdentityId guid -> guid
let! result = conn.QuerySingleOrDefaultAsync< SomeFindResponseType >(
CommandDefinition(findByUserIdAndMediaIdSql, {| id = guidValue.ToString(); mediaId = mediaGuid |}, cancellationToken = ct))
return Option.ofObj result
})
```

What is normally done with this sort of thing. Does anyone have any recommendations? Do most people go with the convenience of the FSharp libs and convert Async to Task and take the hit? Or do you just stick with dapper and maybe make a lightweight query/runner object to make things more functional?

reddit.com
u/theFlyingCode — 11 days ago
▲ 3 r/fsharp+1 crossposts

I am trying to follow, Domain Modelling Made Functional, honestly I am hitting some very annoying walls than expected. Her's my latest annoyance.

I have two worfklow; SignIn and ConfirmSignup.

ConfirmSignup's contract looks something like this:

type SignupError =
    | ValidationFailed of ValidationError list
    | EmailAlreadyExists
    | VerificationCodeDeliveryFailure
    | PasswordPolicyNotMet
    

// Ports
type SignupUser = SignupCommand -&gt; TaskResult&lt;SignupResult, Error&gt;

type SignupWorkflow = SignupRequest -&gt; TaskResult&lt;SignupResult, SignupError&gt;

The flow is:
SignupWorkflow --> Validate Request --> Other business stuff --> Calls port

As you might observe, The erorr type for the port has ValidationFailed error which it got nothing to do with.

Now, Let's say I have added two more ports and one more aggregate? Then, surely, I can't give the flat DU erorr to all of these ports.

I could do follwing:

>type SignupPortError =
| | EmailAlreadyExists
| VerificationCodeDeliveryFailure
| PasswordPolicyNotMet

type SignupError =
| ValidationFailed of ValidationError list
| SignupError of SignupPortErrror (naming is hard!!!!!!!!!!!!)

But the problem is, What if I want to use the port, Signup in another workflow? Now, I have to reference SignupWorfkow's contract file in another Workflow, which it got nothing to do with it!!!!!!!!!!!!!!!!!!!!!

How do you guys resolve this issue?

reddit.com
u/kincade1905 — 9 days ago