adamc@5: (* Copyright (c) 2008, Adam Chlipala adamc@5: * All rights reserved. adamc@5: * adamc@5: * Redistribution and use in source and binary forms, with or without adamc@5: * modification, are permitted provided that the following conditions are met: adamc@5: * adamc@5: * - Redistributions of source code must retain the above copyright notice, adamc@5: * this list of conditions and the following disclaimer. adamc@5: * - Redistributions in binary form must reproduce the above copyright notice, adamc@5: * this list of conditions and the following disclaimer in the documentation adamc@5: * and/or other materials provided with the distribution. adamc@5: * - The names of contributors may not be used to endorse or promote products adamc@5: * derived from this software without specific prior written permission. adamc@5: * adamc@5: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" adamc@5: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE adamc@5: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE adamc@5: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE adamc@5: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR adamc@5: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF adamc@5: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS adamc@5: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN adamc@5: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) adamc@5: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE adamc@5: * POSSIBILITY OF SUCH DAMAGE. adamc@5: *) adamc@5: adamc@5: structure ListUtil :> LIST_UTIL = struct adamc@5: adamc@6: structure S = Search adamc@6: adamc@110: fun mapConcat f = adamc@110: let adamc@110: fun mc acc ls = adamc@110: case ls of adamc@110: [] => rev acc adamc@110: | h :: t => mc (List.revAppend (f h, acc)) t adamc@110: in adamc@110: mc [] adamc@110: end adamc@110: adamc@6: fun mapfold f = adamc@6: let adamc@6: fun mf ls s = adamc@6: case ls of adamc@6: nil => S.Continue (nil, s) adamc@6: | h :: t => adamc@6: case f h s of adamc@6: S.Return x => S.Return x adamc@6: | S.Continue (h', s) => adamc@6: case mf t s of adamc@6: S.Return x => S.Return x adamc@6: | S.Continue (t', s) => S.Continue (h' :: t', s) adamc@6: in adamc@6: mf adamc@6: end adamc@6: adamc@34: fun mapfoldB f = adamc@34: let adamc@34: fun mf ctx ls s = adamc@34: case ls of adamc@34: nil => S.Continue (nil, s) adamc@34: | h :: t => adamc@34: let adamc@34: val (ctx, r) = f (ctx, h) adamc@34: in adamc@34: case r s of adamc@34: S.Return x => S.Return x adamc@34: | S.Continue (h', s) => adamc@34: case mf ctx t s of adamc@34: S.Return x => S.Return x adamc@34: | S.Continue (t', s) => S.Continue (h' :: t', s) adamc@34: end adamc@34: in adamc@34: mf adamc@34: end adamc@34: adamc@26: fun foldlMap f s = adamc@26: let adamc@26: fun fm (ls', s) ls = adamc@26: case ls of adamc@26: nil => (rev ls', s) adamc@26: | h :: t => adamc@26: let adamc@26: val (h', s') = f (h, s) adamc@26: in adamc@26: fm (h' :: ls', s') t adamc@26: end adamc@26: in adamc@26: fm ([], s) adamc@26: end adamc@26: adamc@39: fun foldlMapConcat f s = adamc@39: let adamc@39: fun fm (ls', s) ls = adamc@39: case ls of adamc@39: nil => (rev ls', s) adamc@39: | h :: t => adamc@39: let adamc@39: val (h', s') = f (h, s) adamc@39: in adamc@39: fm (List.revAppend (h', ls'), s') t adamc@39: end adamc@39: in adamc@39: fm ([], s) adamc@39: end adamc@39: adamc@39: fun foldlMapPartial f s = adamc@39: let adamc@39: fun fm (ls', s) ls = adamc@39: case ls of adamc@39: nil => (rev ls', s) adamc@39: | h :: t => adamc@39: let adamc@39: val (h', s') = f (h, s) adamc@39: val ls' = case h' of adamc@39: NONE => ls' adamc@39: | SOME h' => h' :: ls' adamc@39: in adamc@39: fm (ls', s') t adamc@39: end adamc@39: in adamc@39: fm ([], s) adamc@39: end adamc@39: adamc@23: fun search f = adamc@23: let adamc@23: fun s ls = adamc@23: case ls of adamc@23: [] => NONE adamc@23: | h :: t => adamc@23: case f h of adamc@23: NONE => s t adamc@23: | v => v adamc@23: in adamc@23: s adamc@23: end adamc@23: adamc@120: fun mapi f = adamc@120: let adamc@120: fun m i acc ls = adamc@120: case ls of adamc@120: [] => rev acc adamc@120: | h :: t => m (i + 1) (f (i, h) :: acc) t adamc@120: in adamc@120: m 0 [] adamc@120: end adamc@120: adamc@191: fun foldli f = adamc@191: let adamc@191: fun m i acc ls = adamc@191: case ls of adamc@191: [] => acc adamc@191: | h :: t => m (i + 1) (f (i, h, acc)) t adamc@191: in adamc@191: m 0 adamc@191: end adamc@191: adamc@5: end