-- SG library-- Copyright (c) 2009, Neil Brown.-- All rights reserved.-- -- Redistribution and use in source and binary forms, with or without-- modification, are permitted provided that the following conditions are-- met:---- * Redistributions of source code must retain the above copyright-- notice, this list of conditions and the following disclaimer.-- * Redistributions in binary form must reproduce the above copyright-- notice, this list of conditions and the following disclaimer in the-- documentation and/or other materials provided with the distribution.-- * The author's name may not be used to endorse or promote products derived-- from this software without specific prior written permission.---- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS-- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR-- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR-- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.-- | Some types that are very basic vectors. Most of the use that can be made-- of the vectors is in their type-class instances, which support a powerful set-- of operations. For example:---- > fmap (*3) v -- Scales vector v by 3-- > pure 0 -- Creates a vector filled with zeroes-- > v + w -- Adds two vectors (there is a 'Num' instance, basically)---- Plus all the instances for the classes in "Data.SG.Vector", which allows you-- to use 'getX' and so on.---- You will probably want to create more friendly type synonyms, such as:---- > type Vector2 = Pair Double-- > type Vector3 = Triple Double-- > type Line2 = LinePair Double-- > type Line3 = LineTriple DoublemoduleData.SG.Vector.BasicwhereimportControl.ApplicativeimportData.FoldableimportData.TraversableimportData.SG.Vector-- | A pair, which acts as a 2D vector.newtypePaira=Pair(a,a)deriving(Eq,Ord,Show,Read)-- | A triple, which acts as a 3D vector.newtypeTriplea=Triple(a,a,a)deriving(Eq,Ord,Show,Read)-- | A quad, which acts as a 4D vector.newtypeQuada=Quad(a,a,a,a)deriving(Eq,Ord,Show,Read)-- | A pair of (position vector, direction vector) to be used as a 2D line.newtypeLinePaira=LinePair(Paira,Paira)deriving(Eq,Ord,Show,Read)-- | A pair of (position vector, direction vector) to be used as a 3D line.newtypeLineTriplea=LineTriple(Triplea,Triplea)deriving(Eq,Ord,Show,Read)instanceVectorNumPairwherefmapNum1=fmapfmapNum1inv=fmapfmapNum2=liftA2simpleVec=pureinstanceVectorNumTriplewherefmapNum1=fmapfmapNum1inv=fmapfmapNum2=liftA2simpleVec=pureinstanceVectorNumQuadwherefmapNum1=fmapfmapNum1inv=fmapfmapNum2=liftA2simpleVec=pureinstance(Showa,Eqa,Numa)=>Num(Paira)where(+)=fmapNum2(+)(-)=fmapNum2(-)(*)=fmapNum2(*)abs=fmapNum1invabssignum=fmapNum1signumnegate=fmapNum1invnegatefromInteger=simpleVec.fromIntegerinstance(Showa,Eqa,Numa)=>Num(Triplea)where(+)=fmapNum2(+)(-)=fmapNum2(-)(*)=fmapNum2(*)abs=fmapNum1invabssignum=fmapNum1signumnegate=fmapNum1invnegatefromInteger=simpleVec.fromIntegerinstance(Showa,Eqa,Numa)=>Num(Quada)where(+)=fmapNum2(+)(-)=fmapNum2(-)(*)=fmapNum2(*)abs=fmapNum1invabssignum=fmapNum1signumnegate=fmapNum1invnegatefromInteger=simpleVec.fromIntegerinstanceApplicativePairwherepurea=Pair(a,a)(<*>)(Pair(fa,fb))(Pair(a,b))=Pair(faa,fbb)instanceFoldablePairwherefoldrft(Pair(x,y))=x`f`(y`f`t)instanceTraversablePairwheretraversef(Pair(x,y))=Pair<$>liftA2(,)(fx)(fy)instanceApplicativeTriplewherepurea=Triple(a,a,a)(<*>)(Triple(fa,fb,fc))(Triple(a,b,c))=Triple(faa,fbb,fcc)instanceFoldableTriplewherefoldrft(Triple(x,y,z))=x`f`(y`f`(z`f`t))instanceTraversableTriplewheretraversef(Triple(x,y,z))=Triple<$>liftA3(,,)(fx)(fy)(fz)instanceApplicativeQuadwherepurea=Quad(a,a,a,a)(<*>)(Quad(fa,fb,fc,fd))(Quad(a,b,c,d))=Quad(faa,fbb,fcc,fdd)instanceFoldableQuadwherefoldrft(Quad(x,y,z,a))=x`f`(y`f`(z`f`(a`f`t)))instanceTraversableQuadwheretraversef(Quad(x,y,z,a))=Quad<$>((,,,)<$>fx<*>fy<*>fz<*>fa)instanceFunctorPairwherefmap=fmapDefaultinstanceFunctorTriplewherefmap=fmapDefaultinstanceFunctorQuadwherefmap=fmapDefaultinstanceCoordPairwheregetComponents(Pair(a,b))=[a,b]fromComponents(a:b:_)=Pair(a,b)fromComponentsxs=fromComponents$xs++repeat0instanceCoord2PairwheregetX(Pair(a,_))=agetY(Pair(_,b))=binstanceCoordTriplewheregetComponents(Triple(a,b,c))=[a,b,c]fromComponents(a:b:c:_)=Triple(a,b,c)fromComponentsxs=fromComponents$xs++repeat0instanceCoord2TriplewheregetX(Triple(a,_,_))=agetY(Triple(_,b,_))=binstanceCoord3TriplewheregetZ(Triple(_,_,c))=cinstanceCoordQuadwheregetComponents(Quad(a,b,c,d))=[a,b,c,d]fromComponents(a:b:c:d:_)=Quad(a,b,c,d)fromComponentsxs=fromComponents$xs++repeat0instanceCoord2QuadwheregetX(Quad(a,_,_,_))=agetY(Quad(_,b,_,_))=binstanceCoord3QuadwheregetZ(Quad(_,_,c,_))=c