moduleSolutions.Dependent%defaulttotal---------------------------------------------------------------------------------- Length-Indexed Lists--------------------------------------------------------------------------------dataVect:(len:Nat)->Type->TypewhereNil:Vect0a(::):a->Vectna->Vect(Sn)a-- 1len:Lista->NatlenNil=Zlen(_::xs)=S(lenxs)-- 2head:Vect(Sn)a->ahead(x::_)=xhead Nil impossible-- 3tail:Vect(Sn)a->Vectnatail(_::xs)=xstail Nil impossible-- 4zipWith3:(a->b->c->d)->Vectna->Vectnb->Vectnc->VectndzipWith3f[][][]=[]zipWith3f(x::xs)(y::ys)(z::zs)=fxyz::zipWith3fxsyszs-- 5-- Since we only have a `Semigroup` constraint, we can't conjure-- a value of type `a` out of nothing in case of an empty list.-- We therefore have to return a `Nothing` in case of an empty list.foldSemi:Semigroupa=>Lista->MaybeafoldSemi[]=NothingfoldSemi(x::xs)=Just.maybex(x<+>) $ foldSemixs-- 6-- the `Nil` case is impossible here, so unlike in Exercise 4,-- we don't need to wrap the result in a `Maybe`.-- However, we need to pattern match on the tail of the Vect to-- decide whether to invoke `foldSemiVect` recursively or notfoldSemiVect:Semigroupa=>Vect(Sn)a->afoldSemiVect(x::[])=xfoldSemiVect(x::t@(_::_))=x<+>foldSemiVectt-- 7iterate:(n:Nat)->(a->a)->a->Vectnaiterate0__=Niliterate(Sk)fv=v::iteratekf(fv)-- 8generate:(n:Nat)->(s->(s,a))->s->Vectnagenerate0__=Nilgenerate(Sk)fv=let(v',va)=fvinva::generatekfv'-- 9fromList:(as:Lista)->Vect(lengthas)afromList[]=[]fromList(x::xs)=x::fromListxs-- 10-- Lookup the type and implementation of functions `maybe` `const` and-- try figuring out, what's going on here. An alternative implementation-- would of course just pattern match on the argument.maybeSize:Maybea->NatmaybeSize=maybe0(const1)fromMaybe:(m:Maybea)->Vect(maybeSizem)afromMaybeNothing=[]fromMaybe(Justx)=[x]---------------------------------------------------------------------------------- Fin: Safe Indexing into Vectors--------------------------------------------------------------------------------dataFin:(n:Nat)->TypewhereFZ:{0n:Nat}->Fin(Sn)FS:(k:Finn)->Fin(Sn)(++):Vectma->Vectna->Vect(m+n)a(++)[]ys=ys(++)(x::xs)ys=x::(xs++ys)replicate:(n:Nat)->a->Vectnareplicate0_=[]replicate(Sk)x=x::replicatekxzipWith:(a->b->c)->Vectna->Vectnb->VectnczipWith_[][]=[]zipWithf(x::xs)(y::ys)=fxy::zipWithfxsys-- 1update:(a->a)->Finn->Vectna->VectnaupdatefFZ(x::xs)=fx::xsupdatef(FSk)(x::xs)=x::updatefkxs-- 2insert:a->Fin(Sn)->Vectna->Vect(Sn)ainsertvFZxs=v::xsinsertv(FSk)(x::xs)=x::insertvkxsinsertv(FSk)[]impossible-- 3-- The trick here is to pattern match on the tail of the-- vector in the `FS k` case and realize that an empty-- tail is impossible. Otherwise we won't be able to-- convince the type checker, that the vector's tail is-- non-empty in the recursive case.delete:Fin(Sn)->Vect(Sn)a->VectnadeleteFZ(_::xs)=xsdelete(FSk)(x::xs@(_::_))=x::deletekxsdelete(FSk)(x::[])impossible-- 4safeIndexList:(xs:Lista)->Fin(lengthxs)->asafeIndexList(x::_)FZ=xsafeIndexList(x::xs)(FSk)=safeIndexListxsksafeIndexListNil_impossible-- 5finToNat:Finn->NatfinToNatFZ=ZfinToNat(FSk)=S $ finToNatktake:(k:Fin(Sn))->Vectna->Vect(finToNatk)atakeFZx=[]take(FSk)(x::xs)=x::takekxs-- 6minus:(n:Nat)->Fin(Sn)->NatminusnFZ=nminus(Sj)(FSk)=minusjkminus0(FSk)impossible-- 7drop:(k:Fin(Sn))->Vectna->Vect(minusnk)adropFZxs=xsdrop(FSk)(_::xs)=dropkxs-- 8splitAt:(k:Fin(Sn))->Vectna->(Vect(finToNatk)a,Vect(minusnk)a)splitAtkxs=(takekxs,dropkxs)---------------------------------------------------------------------------------- Compile-Time Computations---------------------------------------------------------------------------------- 1flattenList:List(Lista)->ListaflattenList[]=[]flattenList(xs::xss)=xs++flattenListxssflattenVect:Vectm(Vectna)->Vect(m*n)aflattenVect[]=[]flattenVect(xs::xss)=xs++flattenVectxss-- 2take':(m:Nat)->Vect(m+n)a->Vectmatake'0_=[]take'(Sk)(x::xs)=x::take'kxstake'(Sk)Nilimpossibledrop':(m:Nat)->Vect(m+n)a->Vectnadrop'0xs=xsdrop'(Sk)(x::xs)=drop'kxsdrop'(Sk)NilimpossiblesplitAt':(m:Nat)->Vect(m+n)a->(Vectma,Vectna)splitAt'mxs=(take'mxs,drop'mxs)-- 3-- Since we must call `replicate` in the `Nil` case, `k`-- must be a non-erased argument. I used an implicit argument here,-- since this reflects the type of the mathematical function-- more closely.---- Empty matrices probably don't make too much sense,-- so we could also request at the type-level that `k` and `m`-- are non-zero, in which case both values could be derived-- by pattern matching on the vectors.transpose:{k:_}->Vectm(Vectka)->Vectk(Vectma)transpose[]=replicatek[]transpose(xs::xss)=zipWith(::)xs(transposexss)