Halkell singleletons type pack

It's hard for me to convince the compiler that my types are correct. With regular ones Natwith constructors Zero, Succit is quite simple (the goal is to write a function replicatefor length-indexed lists ( Vect)):

replicate' :: SNat n -> a -> Vect n a
replicate' SZero _ = Nil
replicate' (SSucc n) a = a :> replicate' n a

But regular is Natsharply slow.

So, there is a package that displays GHC.TypeLits in the lone library for faster Nats. But I can not get this example to work with it:

sameNat :: forall a b. (KnownNat a, KnownNat b) => SNat a -> SNat b -> Maybe (a :~: b)
sameNat x y
  | natVal (Proxy :: Proxy a) == natVal (Proxy :: Proxy b) = Just (unsafeCoerce Refl)
  | otherwise            = Nothing

replicate'' :: (KnownNat n) => SNat n -> a -> Vect n a
replicate'' n a =
  case sameNat n (sing :: Sing 0) of
    Just Refl -> Nil
    Nothing   -> a ::> replicate'' (sPred n) a

This will not look on the last line:

Couldn't match type ā€˜n’
                     with ā€˜(n GHC.TypeNats.- 1) GHC.TypeNats.+ 1’
+4
source share
2 answers

, sameNat n (sing :: Sing 0) n ~ 0 , n ( Just Refl), n , Nothing. n, , Nothing, sameNat ( , sPred, 1 <= n).

, -, , n ~ 0, , 1 <= n. - :

data IsZero (n :: Nat)
  where Zero :: (0 ~ n) => IsZero n
        NonZero :: (1 <= n) => IsZero n
deriving instance Show (IsZero n)

replicate'' :

isZero :: forall n. SNat n -> IsZero n
isZero n = _

replicate'' :: SNat n -> a -> Vect n a
replicate'' n x = case isZero n
                    of Zero -> Nil
                       NonZero -> x ::> replicate'' (sPred n) x

, isZero, , , Nat.

, isZero. , sameNat, . Data.Singletons.Decide, , . :

isZero :: forall n. SNat n -> IsZero n
isZero n = case n %~ (SNat @0)
             of Proved Refl -> Zero
                Disproved nonsense -> NonZero

, ! Proved ( , sameNat Just Refl, ). " " nonsense, (n :~: 0) -> Void, ( ), "", n :~: 0, , n 0. , 1 <= n; , n 0, 1, , GHC .

- singleton Ord SNat @1 :%<= n:

isZero :: forall n. SNat n -> IsZero n
isZero n = case (SNat @1) %:<= n
             of STrue -> NonZero
                SFalse -> Zero

, STrue SFalse - True False, . , 0 ~ n 1 <= n ( , SNat @0). .

. , ; , < <= , , Nat .

, :

isZero :: forall n. SNat n -> IsZero n
isZero n = case n %~ (SNat @0)
             of Proved Refl -> Zero
                Disproved _ -> unsafeCoerce (NonZero @1)

NonZero , n 1 , - n, , 1 - 1 .

:

{-# LANGUAGE DataKinds
           , GADTs
           , KindSignatures
           , ScopedTypeVariables
           , StandaloneDeriving
           , TypeApplications
           , TypeOperators
  #-}

import GHC.TypeLits ( type (<=), type (-) )
import Data.Singletons.TypeLits ( Sing (SNat), SNat, Nat )
import Data.Singletons.Prelude.Enum ( sPred )
import Data.Singletons.Decide ( SDecide ((%~))
                              , Decision (Proved, Disproved)
                              , (:~:) (Refl)
                              )
import Unsafe.Coerce ( unsafeCoerce )

data IsZero (n :: Nat)
  where Zero :: (0 ~ n) => IsZero n
        NonZero :: (1 <= n) => IsZero n
deriving instance Show (IsZero n)

isZero :: forall n. SNat n -> IsZero n
isZero n = case n %~ (SNat @0)
             of Proved Refl -> Zero
                Disproved _ -> unsafeCoerce (NonZero @1)


data Vect (n :: Nat) a
  where Nil :: Vect 0 a
        (::>) :: a -> Vect (n - 1) a -> Vect n a
deriving instance Show a => Show (Vect n a)

replicate'' :: SNat n -> a -> Vect n a
replicate'' n x = case isZero n
                    of Zero -> Nil
                       NonZero -> x ::> replicate'' (sPred n) x

head'' :: (1 <= n) => Vect n a -> a
head'' (x ::> _) = x

main :: IO ()
main = putStrLn
     . (:[])
     . head''
     $ replicate''
         (SNat @1000000000000000000000000000000000000000000000000000000)
         '\x1f60e'

, KA Buhr, unsafeCoerce, , , Vect n a SNat n, ( iterate Int), , SNat n Vect n a. , ( ), , Refuted _ :: Decision (n :~: 0) 1 <= n, isZero ( , , a SNat ).

, Vect, , "" , GHC Nat, . Data.Constraint.Nat constraints , (, drop :: (k <= n) => SNat k -> Vect n a -> Vect (n - k) a, , , leTrans, , , 1 <= k 1 <= n, , ). , . . , , , . .

+2

, , , , . sameNat , "" , - , case.

, SNat (singleletons), , , unsafeCoerce . , @Ben , - , n , n ( n ), . , , , / , .

(.. , , , ) unsafeCoerce:

replicate1 :: (KnownNat n) => SNat n -> a -> Vect n a
replicate1 n a =
  unsafeCoerce (iterate (unsafeCoerce . (a ::>)) Nil
                !! fromInteger (fromSing n))

, , , ( ) , .

, n, :

{-# LANGUAGE ScopedTypeVariables #-}

replicate2 :: forall a n . (KnownNat n) => a -> Vect n a
replicate2 a =
  unsafeCoerce (iterate (unsafeCoerce . (a ::>)) Nil
        !! fromInteger (fromSing (SNat :: SNat n)))

, :

{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE GADTs               #-}
{-# LANGUAGE KindSignatures      #-}
{-# LANGUAGE TypeOperators       #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE ScopedTypeVariables #-}

import Data.Singletons
import Data.Singletons.Prelude
import Data.Singletons.TypeLits
import Unsafe.Coerce

infixr 5 ::>
data Vect (n :: Nat) a where
  Nil :: Vect 0 a
  (::>) :: a -> Vect (n :- 1) a -> Vect n a

instance (Show a) => Show (Vect n a) where
  showsPrec _ Nil = showString "Nil"
  showsPrec d (x ::> xs) = showParen (d > prec) $
showsPrec (prec+1) x . showString " ::> " . showsPrec prec xs
where prec=5

replicate1 :: (KnownNat n) => SNat n -> a -> Vect n a
replicate1 n a =
  unsafeCoerce (iterate (unsafeCoerce . (a ::>)) Nil
        !! fromInteger (fromSing n))

replicate2 :: forall a n . (KnownNat n) => a -> Vect n a
replicate2 a =
  unsafeCoerce (iterate (unsafeCoerce . (a ::>)) Nil
        !! fromInteger (fromSing (SNat :: SNat n)))

head' :: Vect (n :+ 1) a -> a
head' (x ::> _) = x

tail' :: ((n :+ 1) :- 1) ~ n => Vect (n :+ 1) a -> Vect n a
tail' (_ ::> v) = v

main = do print (replicate2 False   :: Vect 0 Bool)
          print (replicate2 "Three" :: Vect 3 String)
          print (head' (tail' (replicate2 "1M" :: Vect 1000000 String)))

          print (replicate1 (SNat :: SNat 0) False   :: Vect 0 Bool)
          print (replicate1 (SNat :: SNat 3) "Three" :: Vect 3 String)
          print (head' (tail' (replicate1 (SNat :: SNat 1000000) "1M" :: Vect 1000000 String)))
+1

Source: https://habr.com/ru/post/1687120/


All Articles