liquidhaskell-0.8.0.2: tests/strings/todo/StringIndexing.hs
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE GADTs #-}
{-@ LIQUID "--totality" @-}
module StringIndexing where
import GHC.TypeLits
import Data.String
import Data.Proxy
-- Structure that defines valid indeces of a type level target
-- symbol in a value level string
data MI (tagret :: Symbol) s where
MI :: IsString s => s -- input string
-> [Int] -- valid indeces of target in input
-> MI target s
{-@ MI :: input:s
-> [{i:Int | str.substr input i (str.len target) == target }]
-> MI s @-}
-- STEP 1: Verification of valid structures
-- CHALLENGE: String interepretations from SMT
-- THESE SHOULD BE SAFE
misafe1 :: MI "cat" String
misafe1 = MI "catdogcatsdots" []
misafe2 :: MI "cat" String
misafe2 = MI "catdogcatsdots" [1]
misafe3 :: MI "cat" String
misafe3 = MI "catdogcatsdots" [1, 7]
misafe4 :: MI "cat" String
misafe4 = MI "catdogcatsdots" [7, 1]
misafe5 :: MI "cat" String
misafe5 = MI "catdogcatsdots" [7]
-- THIS SHOULD BE UNSAFE
miunsafe :: MI "dog" String
miunsafe = MI "catdogcatsdots" [1]
-- STEP 2: Verify that mempty and mappend satisfy the invariants
{-@ axiomatize mempty @-}
mempty :: forall (target :: Symbol). MI target String
mempty = MI "" []
{-@ axiomatize mappend @-}
mappend :: forall (target :: Symbol). (KnownSymbol target) => MI target String -> MI target String -> MI target String
mappend (MI i1 is1) (MI i2 is2)
= MI input (is1 ++ (map (+ length i1) is2) ++ is)
where
is = filter (\i -> substr input i len == target) [(len1 - len) .. (len1 + len)]
input = i1 ++ i2
len1 = length i1
len = length target
target = symbolVal (Proxy :: Proxy target)
substr :: IsString s => s -> Int -> Int -> s
substr = undefined
-- STEP 3: Verify that mempty and mappend satisfy the monoid laws
mempty_left :: forall (target :: Symbol) s. IsString s => MI target s -> ()
{-@ mempty_left :: x:MI target s -> {mappend mempty x == x } @-}
mempty_left _ = undefined
mempty_right :: forall (target :: Symbol) s. IsString s => MI target s -> ()
{-@ mempty_right :: x:MI target s -> {mappend x mempty == x } @-}
mempty_right _ = undefined
mappend_assoc :: forall (target :: Symbol) s. IsString s => MI target s -> MI target s -> MI target s -> ()
{-@ mappend_assoc :: x:MI target s -> y:MI target s -> z:MI target s
-> {mappend x (mappend y z) == mappend (mappend x y) z } @-}
mappend_assoc _ _ _ = undefined