def dequeue(q: Queue[T]) -> Tuple[Maybe[T], Queue[T]]: match q: case (Queue(Nil(), Nil())): return (Nothing(), Queue(Nil(), Nil())) case (Queue(xs, Cons(y, ys))): return (Just(y), Queue(xs, ys)) case (Queue(Cons(x, xs), Nil())): match reverse(Cons(x, xs)): case Cons(y, ys): return (Just(y), Queue(Nil(), ys)) case _: raise TypeError("match non-exhaustive") case _: raise TypeError("match non-exhaustive")
def firstIndex(condition, xs): # firstIndex : (a -> Bool) . List a -> Maybe Index for ix in range(len(xs)): x = xs[ix] if condition(x): return Just(ix) return Nothing
def systemSolution(matrix, vector): kernelBasis = matrix.right_kernel().basis() try: particularSolution = matrix.solve_right(vector) except: return Nothing s = (kernelBasis, particularSolution) return Just(s)
def uncons(xs): """ uncons :: [a] -> Maybe (a, [a]) Decompose a list into its head and tail. If the list is empty, returns Nothing. If the list is non-empty, returns Just((x, xs)), where x is the head of the list and xs its tail. """ return Just((head(xs), tail(xs))) if not null(xs) else Nothing
def lookup(key, assocs): """ lookup :: Eq a => a -> [(a, b)] -> Maybe b lookup(key, assocs) looks up a key in an association list. """ for k, value in assocs: if k == key: return Just(value) return Nothing
def _parseGroup(tup): def Error(index, message): return Left("system #" + str(index) + ": " + message) (lines, index) = tup one = lines[0].split() two = lines[1].split() line3 = lines[2].strip() line4 = lines[3].strip() if len(one) == 0 or len(two) == 0: return Error(index, "lines 1 or 2 empty") if not forall(one + two, isFraction): return Error(index, "at least one token on line #1 or #2 is not a valid fractional number") n = len(one) np = len(two) if np % n != 0: return Error(index, "number of tokens on line #2 is not multiple of number of tokens on #1") p = np / n if line3 != noSolutionSymbol and line4 != noSolutionSymbol: three = lines[2].split() if not forall(three, isFraction): return Error(index, "at least one token on line #3 is not a valid fractional number") if len(three) != p: return Error(index, "line #3 is the wrong size for being a particular solution") pSol = map(fractionMaker, three) if line4 == nullVecSpaceSymbol: kerBase = [] else: four = line4.split() if not forall(four, isFraction): return Error(index, "at least one token on line #4 is not a valid fractional number") pq = len(four) if pq % p != 0: return Error(index, "number of tokens on line #4 is not multiple of number of token on #3") kerBase = grouped(map(fractionMaker, four), p) maybeSolution = Just((kerBase, pSol)) elif line3 == noSolutionSymbol and line4 == noSolutionSymbol: maybeSolution = Nothing else: return Error(index, "lines #3 and #4 are invalid, somehow") rightSide = map(fractionMaker, one) leftSide = matrixFromList(map(fractionMaker, two), n, p) system = (leftSide, rightSide) out = (system, maybeSolution) return Right(out)
def stripPrefix(xs, ys): """ stripPrefix :: Eq a => [a] -> [a] -> Maybe [a] The stripPrefix function drops the given prefix from a list. It returns Nothing if the list did not start with the prefix given, or Just the list after the prefix, if it does. """ if isPrefixOf(xs, ys): return Just(ys[len(xs)]) return Nothing
def findIndex(f, xs): """ findIndex :: (a -> Bool) -> [a] -> Maybe Int The findIndex function takes a predicate and a list and returns the index of the first element in the list satisfying the predicate, or Nothing if there is no such element. """ for i, x in enumerate(xs): if f(x): return Just(i) return Nothing
def elemIndex(x, xs): """ elemIndex :: Eq a => a -> [a] -> Maybe Int The elemIndex function returns the index of the first element in the given list which is equal (by ==) to the query element, or Nothing if there is no such element. """ for i, a in enumerate(xs): if a == x: return Just(i) return Nothing
def find(p, xs): """ find :: (a -> Bool) -> [a] -> Maybe a The find function takes a predicate and a structure and returns the leftmost element of the structure matching the predicate, or Nothing if there is no such element. """ for x in xs: if p(x): return Just(x) return Nothing
def systemSolution(matrix, rightSide): maybeSystem = maybeSystemInit(matrix, rightSide).maybeDo(echelonized, 0) if maybeSystem == Nothing: # the system has no solution return Nothing else: system = maybeSystem.justValue() if len(system.pivotalLines) == 0: # extreme case: no pivot was found # during the echelonizing (which means the leftside # matrix A is null) and yet its result # is not Nothing, so the system does admit some # solution, so we conclude Y = 0 too, # and the kernel is thereafter the whole domain # of the linear application that could be # associated with A (if A has p columns, # that would canonically be R^p). # A particular solution can be any vector at all, # like the vector null. p = system.leftSideWidth solution = (idMatrix(p), nullVector(p)) return Just(solution) else: pivotalLines = keepPivotalLines(system) return Just(extractSolution(normalized(pivotalLines)))
def echelonized(system, colIndex): #print "DBG" #printMatrix(system.pivotalLines) #printMatrix(system.nonPivotalLines) maybePivotalLineIndex = findPivot(system, colIndex) if maybePivotalLineIndex == Nothing: # pivot not found => this column is filled with zeroes # on the non pivotal lines, so we do nothing maybeSystem = Just(system) else: pivotalLineIndex = maybePivotalLineIndex.justValue() maybeSystem = usePivot(system, pivotalLineIndex, colIndex) if maybeSystem == Nothing: return Nothing else: newSystem = maybeSystem.justValue() if colIndex >= newSystem.leftSideWidth - 1: # we reached the end of recursion, having # walked through all the columns of the leftside # matrix of the equation return Just(newSystem) else: # we repeat the process for the next column return echelonized(newSystem, colIndex + 1)
def functionalTests(): tester = Test(systemSolution) idMat = idMatrix(3) Y1 = [1,2,3] in1 = [idMat, Y1] out1 = Just(([], Y1)) # kernel = {0} io1 = (in1, out1) nullMat = nullMatrix(3,3) Y2 = [4,5,6] in2 = [nullMat, Y2] out2 = Nothing # no solution io2 = (in2, out2) ioList = [io1, io2] indices = range(len(ioList)) for ioIx in zip(ioList, indices): ((inp, out), index) = ioIx tester.check(input = inp, output = out, testName = "test #" + str(index)) tester.printResults()
def testingMatrix(Test): print "==== unit tests for Matrix.py:" # checkDim : Int -> Void Test(checkDim).checkError(input=[0], testName="dim = 0").checkError( input=[-1], testName="dim = -1").printResults() # checkIx : Int . Int -> Void Test(checkIx).checkError(input=[0, 0], testName="0,0").checkError( input=[-1, 5], testName="-1,5").printResults() # nullVector : [Num n] Dim -> Vector n Test(nullVector).check(input=[3], output=[0, 0, 0], testName="dim = 0").printResults() # nullMatrix : [Num n] Dim . Dim -> Matrix n Test(nullMatrix).check(input=[3, 2], output=[[0, 0], [0, 0], [0, 0]], testName="n,p = 3,2").printResults() # unitVector : [Num n] Int . Int -> Vector n Test(unitVector).check(input=[4, 2], output=[0, 0, 1, 0], testName="e2 from R4").printResults() # idMatrix : [Num n] Int -> Matrix n Test(idMatrix).check(input=[3], output=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], testName="Id3").printResults() # matrixFromList : [Num n] List n . Int . Int -> Matrix n Test(matrixFromList).checkError(input=([1, 2, 3], 2, 2), testName="wrong list length").check( input=([1, 2, 3, 4, 5, 6], 3, 2), output=[[1, 2], [3, 4], [5, 6]], testName="some matrix").printResults() # listFromMatrix : [Num n] Matrix n -> List n Test(listFromMatrix).check(input=[[[1, 0], [2, 0], [3, 0]]], output=[1, 0, 2, 0, 3, 0], testName="some matrix").printResults() # ncols : [Num n] Matrix n -> Int Test(ncols).checkError(input=[[1, 2]], testName="a list, not a matrix").check( input=[[[1, 0], [2, 0], [3, 0]]], output=2, testName="some matrix").printResults() # nrows : [Num n] Matrix n -> Int Test(nrows).check(input=[[[1, 0], [2, 0], [3, 0]]], output=3, testName="some matrix").printResults() # isNullVector : [Num n] Vector n -> Bool Test(isNullVector).check(input=[[0, 0, 0, 0]], output=True, testName="yes null").check( input=[[0, 0, 0, 1]], output=False, testName="not null").printResults() # isNullMatrix : [Num n] Matrix n -> Bool Test(isNullMatrix).check(input=[[[0, 0], [0, 0], [0, 0]]], output=True, testName="yes null").check( input=[[[0, 0], [0, 0], [1, 0]]], output=False, testName="not null").printResults() # firstNonNullEachLine : [Num n] Matrix n -> Maybe (List Index) Test(firstNonNullEachLine).check(input=[[[0, 1], [0, 0], [0, 0]]], output=Nothing, testName="one line is null").check( input=[[[0, 1], [1, 0], [1, 0]]], output=Just([1, 0, 0]), testName="foo...fooo").printResults() # columnAt : Index . Matrix t -> Column t Test(columnAt).check(input=[0, [[1, 0], [2, 0], [3, 0]]], output=[1, 2, 3], testName="some matrix").check( input=[1, [[1, 0], [2, 0], [3, 0]]], output=[0, 0, 0], testName="some matrix").checkError( input=[2, [[1, 0], [2, 0], [3, 0]]], testName="wrong index").printResults() # transposed : Matrix t -> Matrix t Test(transposed).check(input=[[[1, 0], [2, 0], [3, 0]]], output=[[1, 2, 3], [0, 0, 0]], testName="some matrix").printResults() # negate : [Num n] Matrix n -> Matrix n Test(negate).check(input=[[[1, 0], [2, 0], [3, 0]]], output=[[-1, 0], [-2, 0], [-3, 0]], testName="some matrix").printResults() # mapMatrix : (a -> b) . Matrix a -> Matrix b def add42(x): return x + 42 Test(mapMatrix).check(input=(add42, [[100, 0], [200, 0], [300, 0]]), output=[[142, 42], [242, 42], [342, 42]], testName="42 forever!").printResults()