Return early with Error from Sequence mapping I have put together this f# code in an attempt to solve the following problem

Given a mapping operation that may not be able to return a value
Cease mapping over the remaining items of a sequence if the mapping operation fails
Append the error to items already mapped and return early

This cannot be achieved with the inbuilt Seq.map and I could not locate any other existing implementations
type OptionFunction&lt;'a, 'b&gt; = 'a -&gt; 'b option
type ResultFunction&lt;'a, 'b, 'c&gt; = 'a -&gt; Result&lt;'b, 'c&gt;

type MaybeProjection&lt;'a,'b,'c&gt; =
    | OptionProjection of OptionFunction&lt;'a,'b&gt;
    | ResultProjection of ResultFunction&lt;'a,'b,'c&gt;

type OptionResultBuilder&lt;'e&gt;() = 
    member _.Return(x) = Result.Ok x
    member _.Bind(m,f) = 
             let r = match m with
                        | Some a -&gt; Ok a
                        | None -&gt; Error Unchecked.defaultof&lt;'e&gt;
             Result.bind f r
    member _.Bind(m,f) = Result.bind f m
    
let orb = OptionResultBuilder()

let mapTillFail mapper s = 
    let rec inner sq =
        seq {
            let mapped = orb {
                let! head = Seq.tryHead sq
                match mapper with
                | OptionProjection a -&gt; 
                    let! m = a head
                    return m
                | ResultProjection a -&gt; 
                    let! m = a head
                    return m
                }                    
                                
            match mapped with
                | Error _ as err-&gt; yield err
                | Ok _ -&gt; 
                    yield mapped
                    yield! sq |&gt; Seq.skip 1 |&gt; inner
        }
    inner s

//code to test it, not part of the implementation
let r = Seq.empty
let s = seq{1..10}

let op = OptionProjection (fun x -&gt; if x &lt; 5 then Some x else None)
let rp = ResultProjection (fun x -&gt; if x &lt; 5 then Ok x else Error &quot;if &gt;= 5&quot;)

r|&gt; mapTillFail op
s|&gt; mapTillFail op
r|&gt; mapTillFail rp
s|&gt; mapTillFail rp

The inbuilt Option and Result types are a natural fit, and I wanted to be able to use a mapping function that returned either of these types.
Despite several attempts to refactor the duplicate statements inside the match mapper with, I just could not not work out how to satisfy the compiler. Every attempt results in the compiler complaining that it can't find a suitable overload for Bind. Suggestions ?
Beyond that I'm largely happy with it for my purposes. But I welcome any other improvements, or comments on issues like performance (at this stage I've not stress tested it).
I can't say, I have the full understanding of computation expressions, so here are some comments that may go in another direction than your purpose with the post:

sq |&gt; Seq.skip 1

can be replaced with
sq |&gt; Seq.tail


I'm not sure, I like that the function returns [ Error null ] for an empty sequence, but that again may be needed in the context? I would expect an empty sequence to return - an empty sequence.

I don't understand the Projection layer, but that may be dictated by the original context.
You could define the type at the function level:
type MaybeFunction&lt;'a, 'b, 'c&gt; = 
    | OptionFunction of ('a -&gt; 'b option)
    | ResultFunction of ('a -&gt; Result&lt;'b, 'c&gt;)

and then create the functions as:
let mbopFunction = OptionFunction (fun x -&gt; if x &lt; 5 then Some x else None)
let mbrsFunction = ResultFunction (fun x -&gt; if x &lt; 5 then Ok x else Error &quot;if &gt;= 5&quot;)

Your main function will then looks like:
let mapTillFail mapper s = 
    let rec inner sq =
        seq {
            let mapped = orb {
                let! head = Seq.tryHead sq
                match mapper with
                | OptionFunction a -&gt; 
                  let! m = a head
                  return m
                | ResultFunction a -&gt; 
                    let! m = a head
                    return m
                }                    
                                
            match mapped with
                | Error _ as err-&gt; yield err
                | Ok _ -&gt; 
                    yield mapped
                    yield! sq |&gt; Seq.tail |&gt; inner
        }
    inner s

which tells that your monad can handle that level without modifications.
Maybe it would be fair to call these function Projections as well as that is what they do?

That said, you can go without the computation expression:
let mapTillFail projection data = 

    let test x =
        let result = 
            match projection with
            | OptionProjection a -&gt; 
                match a x with
                | Some d -&gt; Ok d
                | None -&gt; Error Unchecked.defaultof&lt;'c&gt;
            | ResultProjection a -&gt; a x
        result

    let rec inner lst =
        seq {
            match lst |&gt; Seq.isEmpty with
            | true -&gt; yield Error Unchecked.defaultof&lt;'c&gt;
            | _ -&gt;
                match test (lst |&gt; Seq.head) with
                | Error e -&gt; yield Error e
                | Ok o -&gt;
                    yield Ok o
                    yield! inner (lst |&gt; Seq.tail)
        }

    inner data


Another alternative is to extent the MaybeProjection or MaybeFunction with a member called calculate:
type MaybeFunction&lt;'a, 'b, 'c&gt; = 
    | OptionFunction of ('a -&gt; 'b option)
    | ResultFunction of ('a -&gt; Result&lt;'b, 'c&gt;)
with
member this.Calculate (a) =
    match this with
    | OptionFunction f -&gt; 
        match f a with
        | Some d -&gt; Ok d
        | None -&gt; Error Unchecked.defaultof&lt;'c&gt;
    | ResultFunction f -&gt; f a

used as:
module Seq = 
    let mapTillFail (func: MaybeFunction&lt;'a, 'b, 'c&gt;) data =       
        
        let rec inner lst =
            seq {
                match lst |&gt; Seq.isEmpty with
                | true -&gt; ()
                | _ -&gt;
                    match func.Calculate (lst |&gt; Seq.head) with
                    | Error e -&gt; yield Error e
                    | Ok o -&gt;
                        yield Ok o
                        yield! inner (lst |&gt; Seq.tail)
            }

        inner data

Here I've made an extension to Seq so you can call it like any other Seq functions:
printfn &quot;%A&quot; ((r |&gt; Seq.mapTillFail mbopFunction) |&gt; Seq.toList)
printfn &quot;%A&quot; ((s |&gt; Seq.mapTillFail mbopFunction) |&gt; Seq.toList)
printfn &quot;%A&quot; ((r |&gt; Seq.mapTillFail mbrsFunction) |&gt; Seq.toList)
printfn &quot;%A&quot; ((s |&gt; Seq.mapTillFail mbrsFunction) |&gt; Seq.toList)