VSL - The data.free_semigroup Structure

# Copyright 2011  Petter Urkedal
#
# This file is part of the Viz Standard Library <http://www.vizlang.org/>.
#
# The Viz Standard Library (VSL) is free software: you can redistribute it
# and/or modify it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# The VSL is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
# more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with the VSL.  If not, see <http://www.gnu.org/licenses/>.

open prelude.ubiquitous
open effect

type t α
 inj singleton : α  t α
 inj node : int  t α  t α  t α

let length
    at singleton _ be 1
    at node n _ _ be n

let r_max be 3

let is_valid
    at singleton _ be true
    at node n a b
	let n_a, n_b be length a, length b
	be n = n_a + n_b  n_a  r_max * n_b  n_b  r_max * n_a
	  is_valid a  is_valid b

let cut_within i_min i_max
    at singleton _ fail "cut_within: No place to cut."
    at node n a b
	let n_a be length a
	if i_max < n_a
	    let aL, aR be cut_within i_min i_max a
	    be aL, cat aR b
	if i_min > n_a
	    let bL, bR be cut_within (i_min - n_a) (i_max - n_a) b
	    be cat a bL, bR
	be a, b

let cat a b
    let n_a, n_b be length a, length b
    let n_ab be n_a + n_b
    if n_a > r_max * n_b
	let n_aL_min be int.cdiv n_ab (r_max + 1)
	let n_aL_max be int.div (r_max * n_ab) (r_max + 1)
	let aL, aR be cut_within n_aL_min n_aL_max a
	be node n_ab aL (cat aR b)
    if n_b > r_max * n_a
	let n_bL_min be int.cdiv (n_b - n_a * r_max) (r_max + 1)
	let n_bL_max be int.div  (n_b * r_max - n_a) (r_max + 1)
	let bL, bR be cut_within n_bL_min n_bL_max b
	be node n_ab (cat a bL) bR
    be node n_ab a b

let for_all f
    at singleton x be f x
    at node _ a b be for_all f a  for_all f b

let for_some f
    at singleton x be f x
    at node _ a b be for_some f a  for_some f b

let fold f
    at singleton x be f x
    at node _ a b be fold f b  fold f a

let! iter f
    at singleton x do f x
    at node _ a b do iter f a >> iter f b

let map f
    at singleton x be singleton (f x)
    at node n a b be node n (map f a) (map f b)

let! dump elt_to_string
    at singleton x do print (elt_to_string x)
    at node n a b
	do print (int.show n) >> print "("
	do dump elt_to_string a >> print " * "
	do dump elt_to_string b >> print ")"

in tagged
    let fold f
	let loop i
	    at singleton x be f (i, x)
	    at node _ a b be loop (i + length a) b  loop i a
	be loop 0

    let! iter f
	let! loop i
	    at singleton x do f (i, x)
	    at node _ a b do loop i a >> loop (i + length a) b
	do loop 0

    let for_all f
	let loop i
	    at singleton x be f (i, x)
	    at node _ a b be loop i a  loop (i + length a) b
	be loop 0

    let for_some f
	let loop i
	    at singleton x be f (i, x)
	    at node _ a b be loop i a  loop (i + length a) b
	be loop 0