Created
January 17, 2014 20:35
-
-
Save RaminHAL9001/8480920 to your computer and use it in GitHub Desktop.
BOMDAS, PEMDAS, order of operations. Folding a list of elements where each element is paired with an operator. Providing the operators precedence and associativity, the foldPrec function will infix the elements of the list by the correct order of operations. This is the general case, so it works for anything, not just arithmetic operations.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- "Data/Function/FoldPrec.hs" fold with precedence and associativity. | |
-- | |
-- Copyright (C) 2014 Ramin Honary. | |
-- | |
-- The source code is free software: you can redistribute it and/or | |
-- modify it under the terms of the GNU General Public License as | |
-- published by the Free Software Foundation, either version 3 of the | |
-- License, or (at your option) any later version. | |
-- | |
-- This software 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 General Public License for more details. | |
-- <http://www.gnu.org/licenses/agpl.html>. | |
-- | This modue provides a function 'foldPrec' which folds over a list of operators and operands | |
-- taking operator precedence and associativity into account. | |
module Data.Function.FoldPrec where | |
-- | Every operand must have an integer precedence value assigned to it. | |
type Precedence = Int | |
-- | Every operand must have an associativity value assigned to it. 'Prelude.True' indicates a | |
-- left-associative operator, 'Prelude.False' indicates a right-associative operator. | |
type Associativity = Bool | |
-- | Supply a binding function that combines a left-hand and right-hand operand with an infixed | |
-- operator to produce a new operand. | |
foldPrec | |
:: (operand -> operator -> operand -> operand) | |
-> operand | |
-> [((operator, Precedence, Associativity), operand)] | |
-> operand | |
foldPrec bind left ops = case ops of | |
[] -> left | |
((op, prec, _), right):ops -> case scanRight prec right ops of | |
(right, ops) -> foldPrec bind (bind left op right) ops | |
where | |
scanRight prevPrec left ops = case ops of | |
[] -> (left, []) | |
((op, prec, assoc), right):next -> | |
if prevPrec<prec || (prevPrec==prec && not assoc) | |
then case scanRight prec right next of | |
(right, next) -> scanRight prevPrec (bind left op right) next | |
else (left, ops) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment