This is a more clear one. Check it out https://github.com/darwinia-network/darwinia/blob/4edd24d3cc5ce3bf44fca40e48d79fbd6c94df14/primitives/src/lib.rs#L52-L62.
/// Alias to type for a signature for a transaction on the relay chain. This allows one of several
/// kinds of underlying crypto to be used, so isn't a fixed size when encoded.
pub type Signature = MultiSignature;
/// Alias to the public key used for this chain, actually a `MultiSigner`. Like the signature, this
/// also isn't a fixed size when encoded, as different cryptos have different size public keys.
pub type AccountPublic = <Signature as Verify>::Signer;
/// Alias to the opaque account ID type for this chain, actually a `AccountId32`. This is always
/// 32 bytes.
pub type AccountId = <AccountPublic as IdentifyAccount>::AccountId;
First, we define the Signature
type.
Then, we require that the Signature
is verify-able. How? We require it has implemented the Verify
trait.
And then, the Verify
trait has an associate type Signer
. We take that Signer
as our AccountPublic
.
Finally, we require the AccountPublic
has implemented the IdentifyAccount
. So, we can use its associate type AccountId
as our AccountId
.
Why do we do this?
Because this builds a relationship between these primitives types. We can easily convert/use them.