text:
module Sec8_2z_reverse
import Data.Vect

%default total

{-
 proof is needed for typechecker to replace (k + 1) with (S k) - which is by definition (1 + k)
 plusCommutative 1 k states that 1 + k = k + 1 or (S k) = k + 1
 `rewrite LHS=RHS in ax` rewrites ax replacing RHS with LHS (match on RHS and replace it with LHS)
-}
reverseLemma : Vect (k + 1) elem -> Vect (S k) elem
reverseLemma {k} result = rewrite plusCommutative 1 k in result

myReverse : Vect n elem -> Vect n elem
myReverse [] = []
myReverse (x :: xs) = reverseLemma (myReverse xs ++ [x])

{-
excercise 1:
Write plusCommutative in terms of
plusZeroRightNeutral : (left : Nat) -> left + 0 = left
plusSuccRightSucc : (left : Nat) -> (right : Nat) -> S (left + right) = left + S right

Note need to use `rewrite`, simply using
myPlusCommutes (S k) m = plusSuccRightSucc m k
results in error :

...
Specifically:
        Type mismatch between
                plus m (S k)
        and
                plus m (S k)
-}

myPlusCommutes : (n : Nat) -> (m : Nat) -> n + m = m + n
myPlusCommutes Z m = sym (plusZeroRightNeutral m)
-- myPlusCommutes (S k) m = plusSuccRightSucc m k
myPlusCommutes (S k) m = rewrite myPlusCommutes k m in plusSuccRightSucc m k

{-
excercise:
Finish the following replacing
reverse' acc [] = ?reverseLemma_nil acc
  reverseLemma_nil : Vect n1 a -> Vect (plus n1 0) a
reverse' acc (x :: xs) = ?reverseLemma_xs (reverse' (x::acc) xs)
  reverseLemma_xs : Vect (S (plus n1 len)) a -> Vect (plus n1 (S len)) a
-}

reverseLemma_nil : Vect n1 a -> Vect (plus n1 0) a
reverseLemma_nil {n1} xs = rewrite plusZeroRightNeutral n1 in xs

reverseLemma_xs :  Vect ((S n1) + len) a -> Vect (plus n1 (S len)) a
reverseLemma_xs {n1} {len} xs = rewrite sym (plusSuccRightSucc n1 len) in xs

-- note, (S n1) + len is defnitionally the same as S (n1 + len)
reverseLemma_test :  Vect ((S n1) + len) a -> Vect (S (n1 + len)) a
reverseLemma_test = id

myReverse2 : Vect n a -> Vect n a
myReverse2 xs = reverse' [] xs
   where reverse' : Vect n a -> Vect m a -> Vect (n+m) a
         reverse' acc [] = reverseLemma_nil acc
         reverse' acc (x :: xs)
                       = reverseLemma_xs (reverse' (x::acc) xs)

ext: idr

max_stars_repo_name: rpeszek/IdrisTddNotes

max_issues_repo_name: rpeszek/IdrisTddNotes

max_forks_repo_name: rpeszek/IdrisTddNotes

lm_label:
1. YES
2. YES


text:
module ListSearch

data NatList : Type where
    Nil : NatList
    Cons : (x : Nat) -> (tail : NatList) -> NatList

data Contains : (k : Nat) -> (xs : NatList) -> Type where
    Here : Contains k (Cons k tail)
    There : (later : Contains k tail) -> Contains k (Cons x tail)

total
emptyNoContains : Not (Contains k Nil)
emptyNoContains Here impossible
emptyNoContains (There _) impossible

total
neitherHeadNorTail : (k : Nat) -> (x : Nat) -> (tail : NatList) -> Not (k = x) -> Not (Contains k tail) -> Not (Contains k (Cons x tail))
neitherHeadNorTail k x tail k_neq_x k_not_in_tail in_cons = case in_cons of
    Here => k_neq_x Refl
    (There later) => k_not_in_tail later

total
testContains : (k : Nat) -> (xs : NatList) -> Dec (Contains k xs)
testContains k [] = No emptyNoContains
testContains k (Cons x tail) = case decEq k x of
    (Yes Refl) => Yes Here
    (No contra) =>
        case testContains k tail of
            (Yes prf) => Yes (There prf)
            (No contra2) => No (neitherHeadNorTail k x tail contra contra2)

total
insert : Nat -> NatList -> NatList
insert k xs = case testContains k xs of
    (Yes prf) => xs
    (No contra) => Cons k xs

total
insertProved : (k : Nat) -> (xs : NatList) -> (xs' : NatList ** Contains k xs')
insertProved k xs = case testContains k xs of
    (Yes prf) => (xs ** prf)
    (No contra) => (Cons k xs ** Here)


text:
module Data.Nat.Parity

import Data.Nat

%default total

--------------------------------------------------------------------------------
-- Parity
--------------------------------------------------------------------------------

mutual
  public export
  even : Nat -> Bool
  even Z = True
  even (S k) = odd k

  public export
  odd : Nat -> Bool
  odd Z = False
  odd (S k) = even k

||| A nat is Even when it is twice some other nat.
public export
Even : Nat -> Type
Even n = (half : Nat ** n = half * 2)

||| A nat is Odd when it is one more than twice some other nat.
public export
Odd : Nat -> Type
Odd n = (haf : Nat ** n = S (haf * 2))

||| Two more than an Even is Even.
public export
add2Even : Even n -> Even (2 + n)
add2Even (half ** pf) = (S half ** cong ((+) 2) pf)

||| Two more than an Odd is Odd.
public export
add2Odd : Odd n -> Odd (2 + n)
add2Odd (haf ** pf) = (S haf ** cong ((+) 2) pf)

||| One more than an Even is Odd.
public export
succEvenOdd : Even n -> Odd (S n)
succEvenOdd (half ** pf) = (half ** cong S pf)

||| One more than an Odd is Even.
public export
succOddEven : Odd n -> Even (S n)
succOddEven (haf ** pf) = (S haf ** cong S pf)

||| One less than an Odd is Even.
public export
predOddEven : Odd (S n) -> Even n
predOddEven (haf ** pf) = (haf ** cong Nat.pred pf)

||| A helper fact.
public export
succDoublePredPred : {k : Nat} -> S n = k * 2 -> n = S ((pred k) * 2)
succDoublePredPred {k = Z} prf = absurd prf
succDoublePredPred {k = S _} prf = cong Nat.pred prf

||| One less than an Even is Odd.
public export
predEvenOdd : Even (S n) -> Odd n
predEvenOdd (half ** pf) = (pred half ** succDoublePredPred pf)

||| Every nat is either Even or Odd.
public export
evenOrOdd : (n : Nat) -> Either (Even n) (Odd n)
evenOrOdd Z = Left (0 ** Refl)
evenOrOdd (S k) = case evenOrOdd k of
  Left (half ** pf) => Right (half ** cong S pf)
  Right (haf ** pf) => Left (S haf ** cong S pf)

||| No nat is both Even and Odd.
public export
notEvenAndOdd : {n : Nat} -> Even n -> Odd n -> Void
notEvenAndOdd {n = Z} _ (_ ** odd) = absurd odd
notEvenAndOdd {n = (S k)} (half ** even) (haf ** odd) =
  notEvenAndOdd {n = k}
   (haf ** cong Nat.pred odd)
   (pred half ** succDoublePredPred even)

||| Evenness is decidable.
public export
evenDec : (n : Nat) -> Dec (Even n)
evenDec n = case evenOrOdd n of
  Left even => Yes even
  Right odd => No $ \even => notEvenAndOdd even odd

||| Oddness is decidable.
public export
oddDec : (n : Nat) -> Dec (Odd n)
oddDec n = case evenOrOdd n of
  Left even => No $ notEvenAndOdd even
  Right odd => Yes odd

mutual
  ||| Evens are even.
  public export
  evenEven : {n : Nat} -> Even n -> even n = True
  evenEven {n = Z} _ = Refl
  evenEven {n = S _} pf = oddOdd $ predEvenOdd pf

  ||| Odds are odd.
  public export
  oddOdd : {n: Nat} -> Odd n -> odd n = True
  oddOdd {n = Z} (_ ** pf) = absurd pf
  oddOdd {n = S _} pf = evenEven $ predOddEven pf

max_stars_repo_name: steshaw/hsgames

max_issues_repo_name: steshaw/hsgames

max_forks_repo_name: steshaw/hsgames


text:
module Part2.Sec8_1_eqproof
import Data.Vect

%default total

{-
Returns proof that num1 and num2 are equal

data (=) : a -> b -> Type where
     Refl : x = x
cong : {func : a -> b} -> x = y -> func x = func y
-}
checkEqNat : (num1 : Nat) -> (num2 : Nat) -> Maybe (num1 = num2)
checkEqNat Z Z = Just Refl
checkEqNat Z (S k) = Nothing
checkEqNat (S k) Z = Nothing
checkEqNat (S k) (S j) = case checkEqNat k j of
                              Nothing => Nothing
                              Just prf => Just (cong prf)

{-
Notes: if the last line in defintion of exactLength is changed to
Just prf => ?hole

idris repl:
*Part2/Sec8_1_eqproof> :t hole
  a : Type
  m : Nat
  len : Nat
  prf : len = m
  input : Vect m a
--------------------------------------
hole : Maybe (Vect len a)

When last line is replaced with:
Just prf => Just input
causes compiler error:

./Part2/Sec8_1_eqproof.idr:34:49-58:
   |
34 |                                     Just prf => Just input
   |                                                 ~~~~~~~~~~
When checking right hand side of Part2.Sec8_1_eqproof.case block in exactLength at ./Part2/Sec8_1_eqproof.idr:32:14-29 with expected type
        Maybe (Vect len a)

When checking argument x to constructor Prelude.Maybe.Just:
        Type mismatch between
                Vect m a (Type of input)
        and
                Vect len a (Expected type)

        Specifically:
                Type mismatch between
                        m
                and
                        len

Just prf => ?hole -- Just input

Using rewrite syntax from section 8.2 fixes the problem.
But order of len and m is important
`checkEqNat m len` would not work! (equational profs are not automatically symmetric -
sym function in 8.2)

TODO, also using Dec (section 8.3) fixes the problem, why?
This code compiles fine:

exactLength {m} len input = case decEq m len of
         Yes Refl => Just input
         No contra => Nothing
-}
exactLength : (len : Nat) -> (input : Vect m a) -> Maybe (Vect len a)
exactLength {m} len input
      = case checkEqNat len m of
                                    Nothing => Nothing
                                    Just prf => rewrite prf in Just input  -- syntax from 8.2

{-
`exactLength` implementation in the book (repeated below) does not need `rewrite` syntax.
Maybe because it keeps nat value in scope (look at SameNat constructor) and is Nat sepecific.
The need to have evidence of type/value being checked in scope seems to be important.
This relates to some of my Haskell experience (see F2 type family and solutions to example 1 and 2).
-}

data EqNat : (num1 : Nat) -> (num2 : Nat) -> Type where
     SameNat : (num : Nat) -> EqNat num num

{- nicely generated by Idris by case splitting on third variable (eq) -}
sameS : (k : Nat) -> (j : Nat) -> (eq : EqNat k j) -> EqNat (S k) (S j)
sameS j j (SameNat j) = SameNat (S j)

checkEqNat1 : (num1 : Nat) -> (num2 : Nat) -> Maybe (EqNat num1 num2)
checkEqNat1 Z Z = Just (SameNat Z)
checkEqNat1 Z (S k) = Nothing
checkEqNat1 (S k) Z = Nothing
checkEqNat1 (S k) (S j) = case checkEqNat1 k j of
                              Nothing => Nothing
                              Just eq => Just (sameS _ _ eq)

{- The proof of equality allows this type of method to typecheck and
 rewrite statement is not used. -}
exactLength1 : (len : Nat) -> (input : Vect m a) -> Maybe (Vect len a)
exactLength1 {m} len input
      = case checkEqNat1 m len of
                                    Nothing => Nothing
                                    Just (SameNat len) => Just input

{- exercise 1, (x :) is just a function  -}
same_cons : {xs : List a} -> {ys : List a} ->
                      xs = ys -> x :: xs = x :: ys
same_cons prf = cong prf

{- exercise 2, knowing that x's are indentical, this theorem reduces to same_cons -}
same_lists : {xs : List a} -> {ys : List a} ->
                      x = y -> xs = ys -> x :: xs = y :: ys
same_lists Refl = same_cons

{- exercise 3, 4 -}
data ThreeEqual : a -> b -> c -> Type where
  Refl3 : ThreeEqual a a a

{- Idris knows that all 3 a's are the same, interstingly no need for cong -}
allSameS : (x, y, z : Nat) -> ThreeEqual x y z -> ThreeEqual (S x) (S y) (S z)
allSameS a a a Refl3 = Refl3


text:
module ExactLength

%default total

data Vect : Nat -> Type -> Type where
  Nil : Vect Z a
  (::) : a -> Vect k a -> Vect (S k) a

{-
exactLength :  { m : _ } -> (len : Nat) -> Vect m a -> Maybe (Vect len a)
exactLength len input = case m == len of
                             False => Nothing
                             True => Just input
-}

-- build-up: equality of Nats (EqNat.idr)

data EqNat : Nat -> Nat -> Type where
  Same : (num : Nat) -> EqNat num num

sameS : (eq : EqNat k j) -> EqNat (S k) (S j)
sameS (Same l) = Same (S l)

checkEqNat : (num1 : Nat) -> (num2 : Nat) -> Maybe (EqNat num1 num2)
checkEqNat Z Z = Just (Same Z)
checkEqNat Z _  = Nothing
checkEqNat _ Z = Nothing
checkEqNat (S k) (S l) = case checkEqNat k l of
                              Nothing => Nothing
                              Just eq => Just (sameS eq)

exactLength : { m : Nat } -> (len : Nat) -> Vect m a -> Maybe (Vect len a)
exactLength len input = case checkEqNat m len of
                             Nothing => Nothing
                             Just (Same len) => Just input

-- implementation of checkEqNat using the generic equality type

{-
  data (=) : a -> b -> Type where
    Refl : x = x

  Synonym: Equal
-}

checkEqNat' : (num1 : Nat) -> (num2 : Nat) -> Maybe (num1 = num2)
checkEqNat' Z Z = Just Refl
checkEqNat' Z _  = Nothing
checkEqNat' _ Z = Nothing
checkEqNat' (S k) (S l) = case checkEqNat' k l of
                               Nothing => Nothing
                               Just eq => Just (cong S eq)

exactLength' :  { m : Nat } -> (len : Nat) -> Vect m a -> Maybe (Vect len a)
exactLength' len input = case checkEqNat' m len of
                              Nothing => Nothing
                              Just Refl => Just input

max_stars_repo_name: timmyjose-study/tdd-with-idris

max_issues_repo_name: timmyjose-study/tdd-with-idris

max_forks_repo_name: timmyjose-study/tdd-with-idris


text:
module Srirams.Odds
-- S.Sriram (14487)

import Evens

import Intro

-- 1 --
data IsOdd : Nat -> Type where
  OOdd : IsOdd 1
  SSOdd : (x : Nat) -> (IsOdd x) -> IsOdd (S (S x))

-- 2 --
threeOdd : IsOdd 3
threeOdd = SSOdd 1 OOdd

-- 3 --
twoOdd : IsOdd 2 -> Void
twoOdd (SSOdd Z OOdd) impossible
twoOdd (SSOdd Z (SSOdd _ _)) impossible

-- 4 --
nOddSnEven : (n : Nat) -> (IsOdd n) -> (IsEven (S n))
nOddSnEven (S Z) OOdd = SSEven 0 ZEven
nOddSnEven (S (S x)) (SSOdd x y) = SSEven (S x) (nOddSnEven x y)

-- 5 --
nEvenSnOdd : (n : Nat) -> (IsEven n) -> (IsOdd (S n))
nEvenSnOdd Z ZEven = OOdd
nEvenSnOdd (S (S x)) (SSEven x y) = SSOdd (S x) (nEvenSnOdd x y)

-- 6 --
nEvenOrOdd : (n : Nat) -> Either (IsEven n) (IsOdd n)
nEvenOrOdd Z = Left ZEven
nEvenOrOdd (S k) = case (nEvenOrOdd k) of
                        (Left l) => Right (nEvenSnOdd k l)
                        (Right r) => Left (nOddSnEven k r)

-- 7 --
nNotBothEandO : (n : Nat) -> IsEven n -> IsOdd n -> Void
nNotBothEandO Z ZEven OOdd impossible
nNotBothEandO Z ZEven (SSOdd _ _) impossible
nNotBothEandO (S (S k)) (SSEven k x) (SSOdd k y) = nNotBothEandO k x y

-- 8 --
nmOddaddEven : (n : Nat) -> IsOdd n -> (m: Nat) -> IsOdd m -> IsEven (add n m)
nmOddaddEven (S Z) OOdd (S Z) OOdd = SSEven 0 ZEven
nmOddaddEven (S Z) OOdd (S (S x)) (SSOdd x y) = SSEven (S x) (nOddSnEven x y)
nmOddaddEven (S (S x)) (SSOdd x z) m y = (nOddSnEven (S (add x m)) (nEvenSnOdd (add x m) (nmOddaddEven x z m y)))

-- Auxillary --
aux : (f : Nat -> Nat) -> (n : Nat) -> (m : Nat) -> n = m -> f n = f m
aux f m m (Refl {x = m}) = Refl {x = f m}

-- 9 --
minuOnebyTwo : (n: Nat) -> IsOdd n -> (k: Nat ** S (double k) = n)
minuOnebyTwo (S Z) OOdd = (Z ** Refl {x = 1})
minuOnebyTwo (S (S k)) (SSOdd k x) = step where
  step = case (minuOnebyTwo k x) of
            (m ** pf) => ((S m) ** aux (\l => S (S l)) (S (double m)) k pf)


text:
module Main

import Data.Vect

%default total

addRow :  Num numType
       => (x : Vect cols numType)
       -> (y : Vect cols numType)
       -> Vect cols numType
addRow       []        []  = []
addRow (x :: xs) (y :: ys) = x + y :: addRow xs ys

addMatrix :  Num numType
          => Vect rows (Vect cols numType)
          -> Vect rows (Vect cols numType)
          -> Vect rows (Vect cols numType)
addMatrix       []        []  = []
addMatrix (x :: xs) (y :: ys) = addRow x y :: addMatrix xs ys

tam : Vect 3 (Vect 2 Int)
tam = addMatrix [[ 1, 2]
                ,[ 3, 4]
                ,[ 5, 6]]
                [[ 7, 8]
                ,[ 9,10]
                ,[11,12]]

createEmpties : Vect n (Vect 0 elem)
createEmpties = replicate _ []

transposeHelper :  (x : Vect n elem)
                -> (xsTrans : Vect n (Vect len elem))
                -> Vect n (Vect (S len) elem)
transposeHelper       []        []  = []
transposeHelper (x :: xs) (y :: ys) = (x :: y) :: transposeHelper xs ys

transposeMat :  Vect m (Vect n elem)
             -> Vect n (Vect m elem)
transposeMat       []  = createEmpties
transposeMat (x :: xs) = let xsTrans = transposeMat xs in (transposeHelper x xsTrans)

ttm1 : Vect 2 (Vect 3 Integer)
ttm1 = transposeMat [ [1,2]
                    , [3,4]
                    , [5,6] ]

ttm2 : Vect 4 (Vect 3 Integer)
ttm2 = transposeMat [ [1, 2, 3, 4]
                    , [5, 6, 7, 8]
                    , [9,10,11,12] ]

tmmil : Vect 3 (Vect 2 Integer)
tmmil =        [[ 1,  2]
               ,[ 3,  4]
               ,[ 5,  6]]

tmmir : Vect 2 (Vect 4 Integer)
tmmir = [[ 7, 8, 9,10]
        ,[11,12,13,14]]

ttm3 : Vect 4 (Vect 2 Integer)
ttm3 = transposeMat tmmir

ttm4 : Bool
ttm4 = ttm3    == [[ 7, 11]
                  ,[ 8, 12]
                  ,[ 9, 13]
                  ,[10, 14]]

multRow' :  Num numType
         => (x : Vect m numType)
         -> (y : Vect m numType)
         -> numType
multRow'       []        []  = 0
multRow' (x :: xs) (y :: ys) = x * y + multRow' xs ys

multRow :  Num numType
        => (x : Vect m numType)
        -> (ysTrans : Vect p (Vect m numType))
        -> Vect p numType
multRow x       []  = []
multRow x (y :: ys) = multRow' x y :: multRow x ys

multMatrix :  Num numType
           => Vect n (Vect m numType)
           -> Vect m (Vect p numType)
           -> Vect n (Vect p numType)
multMatrix       []  ys = []
multMatrix (x :: xs) ys =
  let ysTrans = transposeMat ys
  in ((multRow x ysTrans) :: multMatrix xs ys)

tmmr : Vect 3 (Vect 4 Integer)
tmmr = [[ 29, 32, 35, 38]
       ,[ 65, 72, 79, 86]
       ,[101,112,123,134]]

tmm : Bool
tmm = multMatrix tmmil tmmir == tmmr

max_stars_repo_name: haroldcarr/learn-haskell-coq-ml-etc

max_issues_repo_name: haroldcarr/learn-haskell-coq-ml-etc

max_forks_repo_name: haroldcarr/learn-haskell-coq-ml-etc


text:
module PiyushSati.Odds

import Evens

import Intro

--Answer 1
data IsOdd : Nat -> Type where
  OneOdd : IsOdd (S Z)
  SSOdd : (n: Nat) -> IsOdd n -> IsOdd (S(S n))

--Answer 2
ThreeOdd : IsOdd 3
ThreeOdd = SSOdd 1 OneOdd

--Answer 3
TwoEven: IsOdd 2-> Void
TwoEven OneOdd impossible
TwoEven (SSOdd _ _) impossible

--Answer 5

nEvenSnOdd: (n: Nat) -> IsEven n -> IsOdd (S n)
nEvenSnOdd Z ZEven = OneOdd
nEvenSnOdd (S (S n)) (SSEven n nEven) = SSOdd (S n) (nEvenSnOdd n nEven)

--Answer 4

nOddSnEven: (n: Nat) -> IsOdd n -> IsEven (S n)
nOddSnEven (S Z) OneOdd = SSEven Z ZEven
nOddSnEven (S (S n)) (SSOdd n nOdd) = SSEven (S n) (nOddSnEven n nOdd)

--Answer 6

nEvenOrOdd : (n: Nat) -> Either (IsEven n) (IsOdd n)
nEvenOrOdd Z = Left ZEven
nEvenOrOdd (S Z) = Right OneOdd
nEvenOrOdd (S n) =  case (nEvenOrOdd n) of
                       (Left nEven) => Right (nEvenSnOdd n nEven)
                       (Right nOdd) => Left (nOddSnEven n nOdd)

--Answer 7

nEvenAndOdd : (n: Nat) -> IsEven n -> IsOdd n -> Void
nEvenAndOdd Z ZEven OneOdd impossible
nEvenAndOdd (S Z) (SSEven _ _) OneOdd impossible
nEvenAndOdd (S (S n)) (SSEven n x) (SSOdd n y) = nEvenAndOdd n x y

--Answer 8

SumTwoOdd : (n: Nat) -> (m: Nat) -> IsOdd n -> IsOdd m -> IsEven (add n m)
SumTwoOdd (S Z) m OneOdd mOdd = (nOddSnEven m mOdd)
SumTwoOdd (S (S n)) m (SSOdd n nOdd) mOdd = SSEven (add n m) (SumTwoOdd n m nOdd mOdd)

--
apNat : (f: Nat -> Nat) -> (n: Nat) -> (m: Nat) -> n = m -> f n = f m
apNat f m m Refl = Refl

--Answer 9

MinusOneByTwo : (n: Nat) -> IsOdd n -> (m: Nat ** S (double m) = n)
MinusOneByTwo (S Z) OneOdd = (Z **Refl)
MinusOneByTwo (S (S n)) (SSOdd n nOdd) = step where
  step = case (MinusOneByTwo n nOdd) of
            (m ** x) => ((S m) ** apNat (\l => S (S l)) (S(double m)) n x)


text:
module AssRecRule

import Data.Fin
import Data.Vect

{-
 The recursion function for lists of type `a`. Define this by pattern matching
-}
recList : (a: Type) ->  (x: Type) -> x -> (a -> List a -> x -> x) -> (List a -> x)
recList a x base step [] = base
recList a x base step (y :: xs) = step y xs (recList a x base step xs)

{-
Given a list of type `a` and a function `f: a -> b` get a list of type `b`
by applying `f` to each element.
Note: Define using `recList` and without pattern matching on lists.
-}
mapList : (a: Type) -> (b: Type) -> (f: a -> b) -> List a -> List b
mapList a b f x = recList a (List b) [] step2 x where
  step2 : a -> List a -> List b -> List b
  step2 a1 y1 z1 = (f a1) :: z1

{-
Given a list of type `a`, an initial value `init: a` and an operation `op: a -> a -> a`,
get an element of `a` by starting with init and repeatedly applying the elements of the
list,
e.g. fold Nat 1 (*) ([22] :: [3] :: [])  = 1 * 22 * 3
Note: Define using `recList` and without pattern matching on lists.
-}
foldList : (a: Type) ->  (init: a) -> (op : a -> a -> a) -> List a -> a
foldList a init op y = recList a a init step3 y where
  step3 : a -> List a -> a -> a
  step3 a1 la1 a2 = op a2 a1

{-
The induction function on the `Fin` indexed type family. Define this by pattern matching.
-}
inducFin : (xs : (n: Nat) -> Fin n -> Type) -> (base : (m: Nat) -> xs (S m) FZ) -> (step : (p: Nat) -> (k: Fin p) -> (prev: xs p k) -> (xs (S p) (FS k))) -> (q: Nat) -> (j: Fin q) -> xs q j
inducFin xs base step (S q) FZ = base q
inducFin xs base step (S q) (FS x) = step q x (inducFin xs base step q x)

{-
Given a type `a`, a natural number `q`, an element `j : Fin q` and a vector `v` of length q with entries of type `a`,
get the element in position `j` of `v`. Note that this is always well defined.

Note: Define using `inducList` and without pattern matching on the `Fin` family. You may pattern match on Vectors.
The definition should have only one case, and there should be no case splitting on `Fin`.
-}
fetchElem : (a: Type) -> (q: Nat) -> (j: Fin q) -> (Vect q a -> a)
fetchElem a q j = inducFin xs base step q j where
  xs : (n: Nat) -> Fin n -> Type
  xs n m = (Vect n a -> a)
  base : (m: Nat) -> xs (S m) FZ
  base m = basef where
    basef : (Vect (S m) a) -> a
    basef (x :: y) = x
  step : (p: Nat) -> (k: Fin p) -> (prev: xs p k) -> (xs (S p) (FS k))
  step p k prev = stepf where
    stepf : (Vect (S p) a) -> a
    stepf (x :: y) = prev y


text:
module ExerciseOne

import Data.Vect

%default total

-- | Ex1
-- | Write a function:
-- | > repeat : (n : Nat) -> a -> Vect n a
-- | which constructs a vector of n copies of an item.

repeat : (n : Nat) -> a -> Vect n a
repeat Z     _ = []
repeat (S k) e = e :: repeat k e

--------------------------------------------------------------------------------
-- 2. Consider the following functions over Lists:
--     take : Nat -> List a -> List a
--     drop : Nat -> List a -> List a
-- (a) What are the types of the corresponding functions for Vect, vtake and vdrop?
-- Hint: What are the invariants? i.e. how many items need to be in the vector in each case?
-- (b) Implement vtake and vdrop

-- | A. Types for Vect, vtake and vdrop
vtake : (n : Nat) -> Vect (n + m) t -> Vect n t
vtake Z     _         = []
vtake (S k) (x :: xs) = x :: vtake k xs

vdrop : (n : Nat) -> Vect (n + m) t -> Vect m t
vdrop Z     xs        = xs
vdrop (S k) (x :: xs) = vdrop k xs

--------------------------------------------------------------------------------
-- 3. A matrix is a 2-dimensional vector, and could be defined as follows:
Matrix : Nat -> Nat -> Type -> Type
Matrix n m a = Vect n (Vect m a)

-- (a) Using repeat, above, and Vect.zipWith, write a function which transposes a matrix.
-- Hints: Remember to think carefully about its type first! zipWith for vectors is defined as follows:
--         zipWith : (a -> b -> c) -> Vect a n -> Vect b n -> Vect c n
--         zipWith f []      []      = []
--         zipWith f (x::xs) (y::ys) = f x y :: zipWith f xs ys
transpose' : Matrix x y t -> Matrix y x t
transpose' {x = Z} []      = repeat _ []
transpose'         (x::xs) = zipWith (::) x (transpose' xs)

-- (b) Write a function to multiply two matrices.
matX : Num t => Matrix x y t -> Matrix y z t -> Matrix x z t
matX []    _  = []
matX (x::xs) ys = (map (sum . zipWith (*) x) $ transpose' ys) :: (matX xs ys)

--------------------------------------------------------------------------------
-- 4. The following view describes a pair of numbers as a difference:
data Cmp : Nat -> Nat -> Type where
  cmpLT : (y : _) -> Cmp x (x + S y)
  cmpEQ : Cmp x x
  cmpGT : (x : _) -> Cmp (y + S x) y

-- (a) Write the function cmp : (n : Nat) -> (m : Nat) -> Cmp n m
--   which proves that every pair of numbers can be expressed in this way.
-- Hint: recall parity from the lecture. You will find the with construct very useful!
cmp' : (n : Nat) -> (m : Nat) -> Cmp n m
cmp'  Z     Z    = cmpEQ {x = Z}
cmp'  Z    (S k) = cmpLT k
cmp' (S k)  Z    = cmpGT k
cmp' (S k) (S j) with (cmp' k j)
  cmp' (S k) (S k) | cmpEQ = cmpEQ {x = S k}
  cmp' (S k) (S (k + S h)) | cmpLT h = cmpLT h
  cmp' (S (j + S h)) (S j) | cmpGT h = cmpGT h

-- (b) Assume you have a vector xs : Vect a n, where n is unknown.
--   How could you use cmp to construct a suitable input to vtake and vdrop from xs?

-- >>> Huh? What is this even asking?

--------------------------------------------------------------------------------
-- 5. Implement the following functions:
--   plus_nSm : (n : Nat) -> (m : Nat) -> n + S m = S (n + m)
--   plus_commutes : (n : Nat) -> (m : Nat) -> n + m = m + n
--   plus_assoc : (n : Nat) -> (m : Nat) -> (p : Nat) ->
--                n + (m + p) = (n + m) + p

--------------------------------------------------------------------------------
-- 6. One way to define a reverse function for lists is as follows:
--   reverse : List a -> List a
--   reverse xs = revAcc [] xs where
--     revAcc : List a -> List a -> List a
--     revAcc acc [] = acc
--     revAcc acc (x :: xs) = revAcc (x :: acc) xs
-- Write the equivalent function for vectors, vect reverse : Vect a
-- n ->
-- Hint: You can use the same structure as the definition for List, but you will need to think carefully
-- Vect a n
-- about the type for revAcc, and may need to do some theorem proving.

--------------------------------------------------------------------------------
-- 7. You are given the following definition of binary trees:
-- data Tree a = Leaf | Node (Tree a) a (Tree a)
-- Define a membership predicate ElemTree and a function elemInTree which calculates whether a
-- value in in the tree, and a corresponding proof.
--     data ElemTree  : a -> Tree a -> Type where ...
--     elemInTree : DecEq a =>
--                  (x : a) -> (t : Tree a) -> Maybe (ElemTree x t)

max_stars_repo_name: expede/idris-exercises

max_issues_repo_name: expede/idris-exercises

max_forks_repo_name: expede/idris-exercises


text:
module CFT.Splits

import CFT
import Data.Vect

addToCorrectBucket : (value : a)
                  -> {n : Nat}
                  -> (choice : Ty (TyFromNat n) [])
                  -> (vect : Vect n (List a))
                  -> Vect n (List a)
addToCorrectBucket value {n = 0} choice [] = []
addToCorrectBucket value {n = (S k)} (Left Unit) (y :: xs) = (value :: y) :: xs
addToCorrectBucket value {n = (S k)} (Right x) (y :: xs) = y :: addToCorrectBucket value x xs

-- Split a list into `n` lists using a function that allows you to map each element
-- to its `n`th bucket
splitN : (n : Nat) -> (p : a -> Ty (TyFromNat n) []) -> List a -> Vect n (List a)
splitN n p [] = replicate n []
splitN n p (x :: xs) = let check = p x
                           rec = splitN n p xs in
                           addToCorrectBucket x check rec

fromBool : Bool -> Ty (TyFromNat 2) []
fromBool True = Left Unit
fromBool False = Right (Left Unit)

isEven : Nat -> Bool
isEven Z = True
isEven (S k) = not (isEven k)

splitTwoTest : Splits.splitN 2 (Splits.fromBool . Splits.isEven) [1 .. 4] === [[2,4], [1,3]]
splitTwoTest = Refl

--
-- DEFINING POLYNOMIALS
--
-- The goal is to have a type of polynomials that we are going to analyse and
-- see if we can split them into polynomials with 1 solution, 2 solutions or 0 solutions
record Polynomial where
  constructor MkPoly
  x2 : Int -- x squared term
  x : Int -- x term
  c : Int -- constant term

-- A polynomial a * x^2 + b * x + c has
-- 2 solutions if b^2 - 4*a*c > 0
-- 1 solution if b^2 - 4*a*c === 0
-- 0 solutions if b^2 - 4*a*c < 0
solutions : Polynomial -> Ty (TyFromNat 3) []
solutions (MkPoly a b c) =
  let v = b * b - 4 * a * c in
      if v > 0 then Left Unit -- 2 solutions
               else if v == 0 then Right (Left Unit) -- 1 solution
               else Right (Right (Left Unit)) -- no solutions

poly1 : Polynomial
poly1 = MkPoly 2 1 3 -- 0 solutions

poly2 : Polynomial
poly2 = MkPoly (-1) 2 3 -- 2 solutions

poly3 : Polynomial
poly3 = MkPoly 1 2 1 -- 1 solution

split3Test : splitN 3 Splits.solutions [Splits.poly1, Splits.poly2, Splits.poly3]
         === [[Splits.poly2],[Splits.poly3],[Splits.poly1]]
split3Test = Refl

max_stars_repo_name: andrevidela/dev-notes

max_issues_repo_name: andrevidela/dev-notes

max_forks_repo_name: andrevidela/dev-notes


text:
fold_length : (l : List a) -> Nat
fold_length l = foldr (\_, n => S n) 0 l

test_fold_length1 : fold_length [4, 7, 0] = 3
test_fold_length1 = Refl

test_fold_length2 : fold_length [1] = 1
test_fold_length2 = Refl

fold_length_correct : (l : List a) -> fold_length l = length l
fold_length_correct [] = Refl
fold_length_correct (x :: xs) = rewrite fold_length_correct xs in Refl

fold_map : (f : a -> b) -> (l : List a) -> List b
fold_map f l = foldr (\el, acc => f el :: acc) [] l

fold_map_correct : (f : a -> b) -> (l : List a) -> fold_map f l = map f l
fold_map_correct f [] = Refl
fold_map_correct f (x :: xs) = rewrite fold_map_correct f xs in Refl

prod_curry : (f : (a, b) -> c) -> (x : a) -> (y : b) -> c
prod_curry f x y = f (x, y)

prod_uncurry : (f : a -> b -> c) -> (p : (a, b)) -> c
prod_uncurry f (a, b) = f a b

test_map1 : map (+3) [2, 0, 2] = [5, 3, 5]
test_map1 = Refl

uncurry_curry : (f : a -> b -> c) -> (x : a) -> (y : b) -> prod_curry (prod_uncurry f) x y = f x y
uncurry_curry f x y = Refl

curry_uncurry : (f : (a, b) -> c) -> (p : (a, b)) -> prod_uncurry (prod_curry f) p = f p
curry_uncurry f (a, b) = Refl

nth_error : (l : List x) -> (n : Nat) -> Maybe x
nth_error [] n = Nothing
nth_error (h :: l') n =
    if n == 0
        then Just h
        else nth_error l' (pred n)

out_of_bounds_nothing : (n : Nat) -> (l : List a) -> length l = n -> nth_error l n = Nothing
out_of_bounds_nothing (length []) [] Refl = Refl
out_of_bounds_nothing (length (x :: xs)) (x :: xs) Refl =
    rewrite out_of_bounds_nothing (length xs) xs Refl in
        Refl

Church : {x : Type} -> Type
Church {x} = (x -> x) -> x -> x

one : Church
one f x = f x

two : Church
two f x = f $ f x

zero : Church
zero f x = x

three : Church
three f x = f $ f $ f x

succ' : (n : Church {x}) -> Church {x}
succ' n = ?impl

succ1 : succ' zero = one
succ1 = ?succ1_rhs