How does the recursive method work?

Consider the following method count, which maps the natural numbers of a level to level values:

{-# LANGUAGE
    DataKinds
  , KindSignatures
  , PolyKinds
  , FlexibleInstances
  , FlexibleContexts
  , ScopedTypeVariables
  #-}


module Nat where

data Nat = Z | S Nat

data Proxy (a :: k) = Proxy

class Count a where
    count :: a -> Int

instance Count (Proxy Z) where
    count _ = 0

instance Count (Proxy n) => Count (Proxy (S n)) where
    count _ = succ $ count (Proxy :: Proxy n)

It seems to work in repl:

λ count (Proxy :: Proxy (S(S(S Z))) )
3

There Proxymust be some indication to complete the recursion at runtime of the type , but it is assumed that the types will be erased at runtime. I can even replace datawith newtypein the definition Proxy:

newtype Proxy (a :: k) = Proxy ()

- Which would oblige him to have the same representation of memory every time, so that was it Coercible. With that in mind:

  • I do not completely understand how the method is dispatched. I would suggest that:

    • (, ) ⟶ . , , . , , .
    • ⟶ , . - , . , , , .
    • ( , ) ⟶ , ( → ) . , , , , . , - .

     

    , , , - , . - , , :

    • ?
    • ?
    • ? ( , , ?)
    • ?

    ... Et cetera.

  • , , 2 count, 1 . (, Proxy , " A 1 ", 1 Proxy " A 0 ".) . -, , .

, ?

+4
2

, LHS ,

count :: (Count a) => a -> Int

count' :: CountDictionary a -> a -> Int

CountDictionary a ( singleton - !), , , Count, ..

data CountDictionary a = CountDict {
         countMethod :: a -> Int
       }

, TypeApplications:

{-# LANGUAGE AllowAmbiguousTypes, TypeApplications, ScopedTypeVariables, UnicodeSyntax #-}

class Count a where
    count :: Int
 count' :: CountDictionary a -> Int
w/ data CountDictionary a = CountDict Int

instance Count Z where
    count = 0

instance ∀ n . Count n => Count (S n) where
    count = succ $ count @n

, count @(S(S(S Z))),

count @(S(S(S Z)))
  = count' ( CountDict (succ $ count @(S Z)) )
  = count' ( CountDict (succ $ count' (CountDict (succ $ count @Z))) )
  = count' ( CountDict (succ $ count' (CountDict (succ $ count' (CountDict 0)))) )
+7

. .

data Count a = Count { count :: a -> Int }

instance_Count_ProxyZ :: Count (Proxy Z)
instance_Count_ProxyZ = Count { count = \_ -> 0 }

instance_Count_ProxySn :: Count (Proxy n) -> Count (Proxy (S n))
instance_Count_ProxySn context = Count {
  count = \_ -> succ (count context (Proxy :: Proxy n)) }

, count :: Count n => n -> Int, desugarer ( typechecker) n Count n.

, count (Proxy :: Proxy (S (S (S Z)))), Count (S (S (S Z))), Count (Proxy n) -> Count (Proxy (S n)), n ~ S (S Z). , Count (Proxy (S (S Z))) ..

, desugaring count Proxy (S n).

, .

+5

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


All Articles