#another experiment
package require fileutil
set data [fileutil::cat [pwd]/sample1.json]
puts stdout $data
proc charP {ch} {
    pipeset parser .=  {
        pipeswitch {
            #puts "-->$input"
            pipecase = $input |> \
            ,'${ch}'@1.= {list [string range $data 1 end] [string index $data 0] } |> {
                set data
            }
            return nothing
        } 
    }   <ch/0,input/1| $ch
}        

#generate a functor on a pipeline targeting a specific section of the 'value' in: ok {result value}
proc fmap {cmdlist pipeline {restructure ""}} {
    pipeset functor .= {
        pipeswitch {
            pipecase .= list $cmd $p $s $input |cmd@,pipe@,s@,input@> \
            ,'result'@@ok/@0.= { 
                .= list $pipe $input |p@,i@> {{*}$p $i} 
            } |result@@ok/result>  {
                #todo - we need inverse of the destructure operation of pattern-matching 
                #i.e we need restructure - which puts the values in at the matched locations
                #-  (return the updated result without necessarily knowing its full specific structure)
                
            }
        
            return nothing-functor
        }
    } <cmd@,p@,s@,input@| $cmdlist $pipeline $restructure
}

#JSON Parser 100% From Scratch in Haskell (only 111 lines)
#https://www.youtube.com/watch?v=N9RUqGYuGfw
# see also: Understanding parser combinators: a deep dive - Scott Wlaschin https://www.youtube.com/watch?v=RDalzi7mhdY


#produce a pipeline for inner pipeline producing: ok {result {tailchars headchar}} 
#where cmdlist is applied to headchar
proc charP_functor {cmdlist pipeline} {
    pipeset functor .= {
        pipeswitch {
            pipecase .= list $p $input $cmd |pipe@0,input@1,cmd@2> \
            ,'result'@@ok/@0.= { 
                .= list $pipe $input |p@,i@> {{*}$p $i} 
            } |tail@@ok/result/@0,char@@ok/result/@1> {list $tail [{*}$cmd $char] } |
        
            return nothing-functor
        }
    } <p@,cmd@,input/2| $pipeline $cmdlist
}
proc scanc {ch} {
    scan $ch %c
}

p.= charP p

fc.= charP_functor scanc $p