Guest User

Untitled

a guest
Dec 31st, 2025
12
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.77 KB | None | 0 0
  1. -- A fixed-size array.
  2. data Vec (size ∷ Nat) a
  3. = Vec (SmallArray# a)
  4. | Pure a
  5.  
  6. -- Just `SmallArray#` in a Box so we can pass it around
  7. data SA a = SA { unSA ∷ SmallArray# a }
  8.  
  9.  
  10. -- A type-tagged integer that can either be computed at run-time, or
  11. -- statically known if you have KnownNat
  12. data KI (n ∷ Nat) = KI { unKI ∷ Int# }
  13.  
  14. -- like `Vec`, but also gives you the size as a type-tagged Int
  15. pattern SVec s_val as <-
  16. Vec @s_ty as@(sizeofSmallArray#->KI @s_ty->s_val)
  17.  
  18. mkKI ∷ ∀ n -> KnownNat n => KI n
  19. mkKI n | I# i <- fromIntegral $ natVal' (proxy# @n) = KI @n i
  20.  
  21. ----
  22.  
  23. mkVec (KI @s sz) f = Vec @s $ -- Wrap the result immediately!
  24. -- If we did that inside the ST block, checking the constructor
  25. -- tag (Vec or Pure?) would force the array, preventing the
  26. -- more efficient `Pure` cases from actually saving any work.
  27. unSA $ runST $ ST \case
  28. s | (# s, sma #) <- newSmallArray# sz undefined s
  29. , (# s, sa #) <- unsafeFreezeSmallArray# sma $
  30. forI 0# sz s \i -> writeSmallArray# sma i (f i)
  31. -> (# s, SA sa #)
  32.  
  33. forI start end s0 f = go start s0 where
  34. go i (s ∷ State# st)
  35. | 1# <- i <# end = go (i +# 1#) (f i s)
  36. go _ s = s
  37.  
  38. ----
  39.  
  40. instance Functor (Vec s) where
  41. a <$ _ = Pure a
  42. fmap f = \case
  43. Pure a -> Pure (f a)
  44. SVec sa as -> mkVec sa \case
  45. i | (# a #) <- indexSmallArray# as i -> f a
  46.  
  47. -- The Applicative is zippy.
  48. instance Applicative (Vec s) where
  49. pure = Pure; ma <* _ = ma; _ *> mb = mb
  50. liftA2 f = \cases
  51. (Pure a) bs -> fmap (a `f`) bs
  52. as (Pure b) -> fmap (`f` b) as
  53. (SVec sa as) (Vec bs) -> mkVec sa \case
  54. i | (# a #) <- indexSmallArray# as i
  55. , (# b #) <- indexSmallArray# bs i -> f a b
  56.  
  57. -- join picks the main diagonal [(0,0), (1,1), (2,2), ..]
  58. instance Monad (Vec s) where
  59. m >>= f = case m of
  60. Pure a -> f a
  61. SVec sz sa -> mkVec sz \case
  62. i | (# a #) <- indexSmallArray# sa i ->
  63. case f a of
  64. Pure b -> b
  65. Vec sb | (# b #) <- indexSmallArray# sb i -> b
  66.  
  67. -- duplicate produces every rotation of the input vector:
  68. -- transpose . toList . duplicate = toList . duplicate
  69. instance Comonad (Vec s) where
  70. extract = \case
  71. Pure a -> a
  72. Vec sa | (# a #) <- indexSmallArray# sa 0# -> a
  73. extend f = \case
  74. Pure a -> Pure (f (Pure a))
  75. SVec sz@(KI s#) sa -> mkVec sz \i -> f $ mkVec sz \case
  76. j | (# a #) <- indexSmallArray# sa (remInt# (i +# j) s#) -> a
  77.  
  78. ----
  79.  
  80. toFree = diagonal $ satisfy \a -> (a == (2,2)) <$ do
  81. lift $ vecFromListKI (mkKI 5) "lorem"
  82. tell $ Sum 1
  83.  
  84. -- ghci> print $ runWriterT $ runFree (toFree coords)
  85. -- Vec [(Just (2,2),Sum {getSum = 15}),(Just (2,2),Sum {getSum = 15}),(Just (2,2),Sum {getSum = 15}),(Just (2,2),Sum {getSum = 15}),(Just (2,2),Sum {getSum = 15})]
Add Comment
Please, Sign In to add comment