What level of Haskell is required to write average smart contracts?

I’d like to plan some study time to put into Haskell, but a bit unsure if that’s the right path to go as I work full-time as a Software developer - which Rust seems a better bet in terms of employment or paying bills; I’ve actually noticed that some teams are working on Rust libraries for Cardano’s Plutus smart contracts, this would be great, as while I understand why we need Haskell, not all smart contract development should require it, IMO.

Early this year, started the Haskell journey and shared some thoughts/articles, such as:


There were some other articles related to Plutus, which I haven’t published; As I wasn’t confident. Time passes and already forgotten everything but still wondering what’d be the best path to take in the future, as I’d like to write my own protocols.

The impression that I get from Haskell is that’d it’d take years to be minimally productive; and for someone my age, that’d be hard to justify the time.

My question is about what sort of level, it’d be required to write a smart contract at a level of, as an example, EIP-721 or EIP-20 (I understand Cardano has support for tokens natively, this is just to expose the level of difficulty, to communicate to you what sort of level I’d expect to be able to write).

Let me know your thoughts or any experience you might have to help me out make the decision,
Thank you very much for reading :+1:

1 Like

What kind of smart contracts do you want to develop?

In my experience Haskell doesn’t seem to be the difficult part, but rather the whole Plutus environment built around it.

I’ve personally given up on Plutus (I also think Plutus is very difficult to audit by non-experts, which kind of defeats the point).

You could have a look at GitHub - OpenEngineer/plutus-light: Plutus-Light as an alternative (disclaimer: I wrote it).


@Christian_Schmitz I :heart_eyes: GitHub - OpenEngineer/plutus-light: Plutus-Light

1 Like

We’re working on a syntax update.
It’s a bit more rust-like now (hopefully without sacrificing simplicity though)


struct VestingTranche {
    time:  Time, // 'amount' is available after 'time'
    amount: Value

struct VestingParams {
    tranche1: VestingTranche,
    tranche2: VestingTranche,
    owner:    PubKeyHash

const PARAMS: VestingParams = VestingParams{
    /*parameters interpolated from surrounding js*/

func available_from(tranche: VestingTranche, time: Time) -> Value {
    if (time >= tranche.time) {
    } else {

func remaining_from(tranche: VestingTranche, time: Time) -> Value {
    tranche.amount - available_from(tranche, time)

// the compiler is smart enough to add an empty Datum and empty Redeemer as arguments to the actual main entrypoint function
func main(ctx: ScriptContext) -> Bool {
    tx: Tx = ctx.tx;
    now: Time = tx.now();
    remaining_actual: Value = tx.value_locked_by(ctx.current_validator_hash());
    remaining_expected: Value = remaining_from(PARAMS.tranche1, now) + remaining_from(PARAMS.tranche2, now);
    remaining_actual >= remaining_expected && tx.is_signed_by(PARAMS.owner)

What do you think?

1 Like