<commit_before>﻿namespace FSharpPlus

open System.Text
open System.Runtime.InteropServices
open FsControl
open FSharpPlus
open FSharpPlus.Extensions

/// A type-safe list that contains at least one element.
type NonEmptyList<'t> = {Head: 't; Tail: 't list} with
    interface System.Collections.Generic.IEnumerable<'t> with member x.GetEnumerator() = (let {Head = x; Tail = xs} = x in seq (x::xs)).GetEnumerator()
    interface System.Collections.IEnumerable             with member x.GetEnumerator() = (let {Head = x; Tail = xs} = x in seq (x::xs)).GetEnumerator() :> System.Collections.IEnumerator
    member this.head = let {Head = a; Tail = _} = this in a
    member this.tail = let           {Tail = a} = this in a
    member this.Item = function 0 -> this.head | n -> this.tail.[n-1]
    member this.GetSlice = function
        | None  , None
        | Some 0, None
        | Some 0, Some 0 -> this
        | Some a, None   -> let {Head = _; Tail = xs} = this in {Head = xs.[a-1]; Tail = xs.[a..   ]}
        | None  , Some b 
        | Some 0, Some b -> let {Head = x; Tail = xs} = this in {Head = x       ; Tail = xs.[ ..b-1]}
        | Some a, Some b -> let {Head = _; Tail = xs} = this in {Head = xs.[a-1]; Tail = xs.[a..b-1]}

/// Basic operations on NonEmptyList
[<RequireQualifiedAccess>]
module NonEmptyList =
    let create x xs = {Head = x; Tail = xs}
    let singleton x = {Head = x; Tail = []}
    let toList {Head = x; Tail = xs} = x::xs
    let toSeq  {Head = x; Tail = xs} = seq { yield x; yield! xs; }
    let map f  {Head = x; Tail = xs} = {Head = f x; Tail = List.map f xs}
    let cons e {Head = x; Tail = xs} = {Head = e  ; Tail = x::xs}
    let rec tails s =
        let {Tail = xs} = s
        match xs with
        | []   -> {Head = s; Tail = []}
        | h::t -> cons s (tails {Head = h; Tail = t})
         
type NonEmptyList with
    static member Map (x:NonEmptyList<'a>, f:'a->'b) = NonEmptyList.map f x
        
    static member Bind ({Head = x; Tail = xs}, f:_->NonEmptyList<'b>  ) =
        let {Head = y; Tail = ys} = f x
        let ys' = List.collect (NonEmptyList.toList << f) xs
        {Head = y; Tail = (ys @ ys')}

    static member Return (x:'a) = {Head = x; Tail = []}
    static member (<*>)  (f:NonEmptyList<'T->'U>, x:NonEmptyList<'T>) = 
        let r = NonEmptyList.toList f <*> NonEmptyList.toList x
        {Head = r.Head; Tail = r.Tail}

    static member Extract    {Head = h; Tail = _} = h : 't
    static member Duplicate (s:NonEmptyList<'a>, [<Optional>]_impl:Duplicate) = NonEmptyList.tails s
    static member Extend    (s, g) = NonEmptyList.map g (NonEmptyList.tails s) :NonEmptyList<'b>
    

    static member Append ({Head = h; Tail = t},  x) = {Head = h; Tail = t @ NonEmptyList.toList x}

    static member FoldBack ({Head = x; Tail = xs}, f, z) = List.foldBack f (x::xs) z
    static member ToList   (s:NonEmptyList<'a>, [<Optional>]_impl:ToList) = NonEmptyList.toList s
    static member ToSeq    (s:NonEmptyList<'a>, [<Optional>]_impl:ToSeq ) = NonEmptyList.toList s |> List.toSeq
    static member inline Traverse (s:NonEmptyList<'T>, f:'T->'``Functor<'U>``) =
        (NonEmptyList.create << List.head |> fun f x -> f x (List.tail x)) <!> traverse f (toList s) : '``Functor<'NonEmptyList<'U>>``

    static member inline ToString (s:NonEmptyList<'a>, [<Optional>]_impl:ToString) = fun (k:System.Globalization.CultureInfo) ->
            let b = StringBuilder()
            let inline append (s:string) = b.Append s |> ignore
            append "NonEmptyList ["
            let withSemiColons = NonEmptyList.toSeq s |> Seq.map (toStringWithCulture k) |> Seq.intersperse "; "
            Seq.iter append withSemiColons
            append "]"
            b.ToString()

    static member Replace (source:NonEmptyList<'T>, oldValue:NonEmptyList<'T>, newValue:NonEmptyList<'T>, _impl:Replace ) =
        let lst = source |> NonEmptyList.toSeq  |> Seq.replace oldValue newValue |> Seq.toList
        {Head = lst.Head; Tail = lst.Tail}<commit_msg>Make it work in F# 4.1 Looks like an intermediate step with an additional named type is needed in order to propagete all the constraints. This problem existed in F# 4.0 it just that now it seems to appear "earlier" in some cases like this.<commit_after>﻿namespace FSharpPlus

open System.Text
open System.Runtime.InteropServices
open FsControl
open FSharpPlus
open FSharpPlus.Extensions

/// A type-safe list that contains at least one element.
type NonEmptyList<'t> = {Head: 't; Tail: 't list} with
    interface System.Collections.Generic.IEnumerable<'t> with member x.GetEnumerator() = (let {Head = x; Tail = xs} = x in seq (x::xs)).GetEnumerator()
    interface System.Collections.IEnumerable             with member x.GetEnumerator() = (let {Head = x; Tail = xs} = x in seq (x::xs)).GetEnumerator() :> System.Collections.IEnumerator
    member this.head = let {Head = a; Tail = _} = this in a
    member this.tail = let           {Tail = a} = this in a
    member this.Item = function 0 -> this.head | n -> this.tail.[n-1]
    member this.GetSlice = function
        | None  , None
        | Some 0, None
        | Some 0, Some 0 -> this
        | Some a, None   -> let {Head = _; Tail = xs} = this in {Head = xs.[a-1]; Tail = xs.[a..   ]}
        | None  , Some b 
        | Some 0, Some b -> let {Head = x; Tail = xs} = this in {Head = x       ; Tail = xs.[ ..b-1]}
        | Some a, Some b -> let {Head = _; Tail = xs} = this in {Head = xs.[a-1]; Tail = xs.[a..b-1]}

/// Basic operations on NonEmptyList
[<RequireQualifiedAccess>]
module NonEmptyList =
    let create x xs = {Head = x; Tail = xs}
    let singleton x = {Head = x; Tail = []}
    let toList {Head = x; Tail = xs} = x::xs
    let toSeq  {Head = x; Tail = xs} = seq { yield x; yield! xs; }
    let map f  {Head = x; Tail = xs} = {Head = f x; Tail = List.map f xs}
    let cons e {Head = x; Tail = xs} = {Head = e  ; Tail = x::xs}
    let rec tails s =
        let {Tail = xs} = s
        match xs with
        | []   -> {Head = s; Tail = []}
        | h::t -> cons s (tails {Head = h; Tail = t})
         
type NonEmptyList with
    static member Map (x:NonEmptyList<'a>, f:'a->'b) = NonEmptyList.map f x
        
    static member Bind ({Head = x; Tail = xs}, f:_->NonEmptyList<'b>  ) =
        let {Head = y; Tail = ys} = f x
        let ys' = List.collect (NonEmptyList.toList << f) xs
        {Head = y; Tail = (ys @ ys')}

    static member Return (x:'a) = {Head = x; Tail = []}
    static member (<*>)  (f:NonEmptyList<'T->'U>, x:NonEmptyList<'T>) = 
        let r = NonEmptyList.toList f <*> NonEmptyList.toList x
        {Head = r.Head; Tail = r.Tail}

    static member Extract    {Head = h; Tail = _} = h : 't
    static member Duplicate (s:NonEmptyList<'a>, [<Optional>]_impl:Duplicate) = NonEmptyList.tails s
    static member Extend    (s, g) = NonEmptyList.map g (NonEmptyList.tails s) :NonEmptyList<'b>
    

    static member Append ({Head = h; Tail = t},  x) = {Head = h; Tail = t @ NonEmptyList.toList x}

    static member FoldBack ({Head = x; Tail = xs}, f, z) = List.foldBack f (x::xs) z
    static member ToList   (s:NonEmptyList<'a>, [<Optional>]_impl:ToList) = NonEmptyList.toList s
    static member ToSeq    (s:NonEmptyList<'a>, [<Optional>]_impl:ToSeq ) = NonEmptyList.toList s |> List.toSeq
    static member inline Traverse (s:NonEmptyList<'T>, f:'T->'``Functor<'U>``) =
        let lst = traverse f (toList s) : '``Functor<'List<'U>>``
        (NonEmptyList.create << List.head |> fun f x -> f x (List.tail x)) <!> lst : '``Functor<'NonEmptyList<'U>>``

    static member inline ToString (s:NonEmptyList<'a>, [<Optional>]_impl:ToString) = fun (k:System.Globalization.CultureInfo) ->
            let b = StringBuilder()
            let inline append (s:string) = b.Append s |> ignore
            append "NonEmptyList ["
            let withSemiColons = NonEmptyList.toSeq s |> Seq.map (toStringWithCulture k) |> Seq.intersperse "; "
            Seq.iter append withSemiColons
            append "]"
            b.ToString()

    static member Replace (source:NonEmptyList<'T>, oldValue:NonEmptyList<'T>, newValue:NonEmptyList<'T>, _impl:Replace ) =
        let lst = source |> NonEmptyList.toSeq  |> Seq.replace oldValue newValue |> Seq.toList
        {Head = lst.Head; Tail = lst.Tail}
{'fraction_non_alphanumeric': 0.14951807228915662, 'fraction_numerical': 0.002891566265060241, 'mean_word_length': 2.6233085988651244, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 103, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2989346', 'n_tokens_mistral': 2948, 'n_tokens_neox': 2867, 'n_words': 895}