diff --git a/examples/clifford.jl b/examples/clifford.jl
index daf0c12..892be58 100644
--- a/examples/clifford.jl
+++ b/examples/clifford.jl
@@ -4,25 +4,25 @@
 # ## Pauli Strings
 # A pauli string is a tensor product of Pauli operators acting on different qubits. [`PauliString`](@ref) is a subtype of [`CompositeBlock`] with a field `ids` storing the Pauli operators. We can define pauli string with [`PauliString`](@ref) or [`paulistring`](@ref).
 using TensorQEC, TensorQEC.Yao
-PauliString(2,1, 4, 3) # X_1Z_3Y_4
+PauliString(X, I2, Z, Y) # X_1Z_3Y_4
 
-paulistring(4, 2, (1, 2, 4)) # X_1X_2X_4
+paulistring(4, X, (1, 2, 4)) # X_1X_2X_4
 
-# We can use [`Yao.mat`] to get the matrix representation of a Pauli string.
-mat(ComplexF64, PauliString(2,4)) # X_1Z_2
+# We can use `Yao.mat` to get the matrix representation of a Pauli string.
+mat(ComplexF64, PauliString(X, Z)) # X_1Z_2
 
 # ## Pauli Basis
 # [`pauli_basis`](@ref) generates all the Pauli strings of a given length. Those Pauli strings are stored in a high-dimensional array.
 pauli_basis(2)
 
 # [`pauli_decomposition`](@ref) returns the coefficients of a matrix in the Pauli basis.
-pauli_decomposition(mat(ConstGate.CNOT))
+pauli_decomposition(ConstGate.CNOT)
 
 # That implies that $CNOT = \frac{1}{2} (I \otimes I + I \otimes X + Z \otimes I - Z \otimes X)$. We can check this by
 0.5*(mat(kron(I2,I2) + kron(I2,X) + kron(Z,I2) - kron(Z,X))) == mat(ConstGate.CNOT)
 
 # [`pauli_mapping`](@ref) returns the matrix representation of a quantum gate in the Pauli basis. For Hadamard gate H, we know that $HIH = I, HXH = Z, HYH = -Y, HZH = X$. We can convert $H$ into the Pauli basis.
-pauli_mapping(mat(H))
+pauli_mapping(H)
 
 # ## Clifford Group
 # Clifford group can be generated by Hadamard gate, S gate and CNOT gate[^Bravyi2022]. We can generate the Clifford group with [`clifford_group`](@ref).
@@ -31,12 +31,12 @@ clifford_group(1)
 # Each element in the Clifford group acts on pauli basis as a permutation matrix.
 # For $n= 1, 2$, and $3$, this group contains $24$, $11520$, and $92897280$ elements, respectively.
 # We can use [`to_perm_matrix`](@ref) to convert a matrix into a permutation matrix.
-pm = to_perm_matrix(Int8, Int, H)
+pm = to_perm_matrix(H)
 pm.perm, pm.vals
 
 # With the permutation matrix, we can apply a Clifford gate to a Pauli string by [`perm_of_paulistring`](@ref). Here we apply the Hadamard gate to the second qubit of Pauli string $I_1X_2$ and get $I_1Z_2$ with a phase $1$.
-ps1 = PauliString((1, 2))
-ps2, phase = perm_of_paulistring(pm, ps1, [2])
+ps1 = PauliString(I2, X)
+ps2, phase = perm_of_paulistring(ps1, [2]=>pm)
 ps1, ps2, phase
 
 # Put those all together, we can apply a Clifford circuit to a Pauli string by [`clifford_simulate`](@ref).
@@ -44,7 +44,7 @@ qc = chain(put(5, 1 => H), control(5, 1, 2 => Z), control(5, 3, 4 => X), control
 vizcircuit(qc)
 
 # Apply the circuit to Pauli string $Z_1Y_2I_3Y_4X_5$, we get $Y_1X_2Y_3Y_4Y_5$ with a phase $1$.
-ps = PauliString((4, 3, 1, 3, 2))
+ps = PauliString(Z, Y, I2, Y, X)
 ps2, phase = clifford_simulate(ps, qc)
 
 # where `ps2` is the Pauli string after the Clifford circuit and `phase` is the phase factor. It corresponds to the following quantum circuit.
diff --git a/src/cliffordgroup.jl b/src/cliffordgroup.jl
index d5d459f..4d0d226 100644
--- a/src/cliffordgroup.jl
+++ b/src/cliffordgroup.jl
@@ -22,8 +22,7 @@ function clifford_generators(n::Int)
 end
 
 """
-    to_perm_matrix(::Type{T}, ::Type{Ti}, m::AbstractMatrix; atol=1e-8)
-    to_perm_matrix(::Type{T}, ::Type{Ti}, m::AbstractBlock; atol=1e-8)
+    to_perm_matrix([::Type{T}, ::Type{Ti}, ]matrix_or_yaoblock; atol=1e-8)
 
 Convert a Clifford gate to its permutation representation.
 
@@ -36,6 +35,7 @@ Convert a Clifford gate to its permutation representation.
 ### Returns
 - `pm`: The permutation matrix. pm.perm is the permutation vector, pm.vals is the phase factor.
 """
+to_perm_matrix(m::AbstractBlock; atol=1e-8) = to_perm_matrix(Int8, Int, m; atol)
 to_perm_matrix(::Type{T}, ::Type{Ti}, m::AbstractBlock; atol=1e-8) where {T, Ti} = to_perm_matrix(T, Ti, pauli_repr(m); atol)
 function to_perm_matrix(::Type{T}, ::Type{Ti}, m::AbstractMatrix; atol=1e-8) where {T, Ti}
     @assert all(j -> count(i->abs(i) > atol, view(m, :, j)) == 1, 1:size(m, 2))
@@ -84,15 +84,16 @@ end
 Map the Pauli string `ps` by a permutation matrix `pm`. Return the mapped Pauli string and the phase factor.
 
 ### Arguments
-- `pm`: The permutation matrix.
 - `ps`: The Pauli string.
-- `pos`: The positions where the permuation is applied.
+- `operation`: A pair of the positions to apply the permutation and the permutation matrix.
 
 ### Returns
 - `ps`: The mapped Pauli string.
 - `val`: The phase factor.
 """
-function perm_of_paulistring(pm::PermMatrix, ps::PauliString, pos::Vector{Int})
+function perm_of_paulistring(ps::PauliString, operation::Pair{Vector{Int}, <:PermMatrix})
+    pos, pm = operation
+    @assert 4^length(pos) == length(pm.perm)
     v = collect(ps.ids)
     ps_perm_num = 1+sum((ps.ids[pos] .-1) .* [4^i for i in 0:length(pos)-1])
     v[pos]=[mod(div(pm.perm[ps_perm_num]-1, 4^(j-1)), 4)+1 for j in 1:length(pos)]
@@ -111,13 +112,13 @@ function clifford_simulate(ps::PauliString, qc::ChainBlock)
         gate = toput(_gate)
         key = hash(gate.content)
         if haskey(gatedict, key) 
-            ps, val = perm_of_paulistring(gatedict[key], ps, collect(gate.locs))
+            ps, val = perm_of_paulistring(ps, collect(gate.locs)=>gatedict[key])
         else 
             pm = to_perm_matrix(Int8, UInt8, pauli_repr(mat(gate.content)))
             push!(gatedict, key => pm)
-            ps,val = perm_of_paulistring(pm, ps, collect(gate.locs))
+            ps,val = perm_of_paulistring(ps, collect(gate.locs)=>pm)
         end
         valf *= val
     end
     return ps,valf
-end
\ No newline at end of file
+end
diff --git a/src/paulibasis.jl b/src/paulibasis.jl
index 21c4869..2fd10f1 100644
--- a/src/paulibasis.jl
+++ b/src/paulibasis.jl
@@ -25,21 +25,25 @@ end
 
 Decompose a matrix into the Pauli basis.
 """
-function pauli_decomposition(m::AbstractMatrix)
+function pauli_decomposition(m::AbstractMatrix{T}) where T
 	nqubits = Int(log2(size(m, 1)))
-	return [tr(mat(pauli) * m) for pauli in pauli_basis(nqubits)] / (2^nqubits)
+	return [tr(mat(T, pauli) * m) for pauli in pauli_basis(nqubits)] / (2^nqubits)
 end
+pauli_decomposition(::Type{T}, m::AbstractBlock) where T = pauli_decomposition(mat(T, m))
+pauli_decomposition(m::AbstractBlock) = pauli_decomposition(ComplexF64, m)
 
 """
     pauli_mapping(m::AbstractMatrix)
 
-Convert a linear operator into the Pauli basis.
+Convert a linear operator to a matrix in the Pauli basis.
 """
 function pauli_mapping(m::AbstractMatrix)
 	nqubits = Int(log2(size(m, 1)))
 	paulis = pauli_basis(nqubits)
 	return [real(tr(mat(pi) * m * mat(pj) * m')/size(m, 1)) for pi in paulis, pj in paulis]
 end
+pauli_mapping(::Type{T}, m::AbstractBlock) where T = pauli_mapping(mat(T, m))
+pauli_mapping(m::AbstractBlock) = pauli_mapping(ComplexF64, m)
 
 function pauli_group(n::Int)
     return [coeff => PauliString(ci.I) for coeff in 0:3, ci in CartesianIndices(ntuple(_ -> 4, n))]
@@ -66,4 +70,4 @@ end
 function pauli_string_map(ps::PauliString{N}, paulimapping::Array, qubits::Vector{Int}) where N
     c=findall(!iszero, paulimapping[fill(:,length(size(paulimapping)) ÷ 2)...,ps.ids[qubits]...])[1]
     return PauliString(([k ∈ qubits ? c[findfirst(==(k),qubits)] : ps.ids[k] for k in 1:N]...,))
-end
\ No newline at end of file
+end
diff --git a/src/paulistring.jl b/src/paulistring.jl
index 4c2abfe..78e8ff5 100644
--- a/src/paulistring.jl
+++ b/src/paulistring.jl
@@ -190,5 +190,7 @@ densitymatrix2sumofpaulis(dm::DensityMatrix) = tensor2sumofpaulis(real.(pauli_de
 Create a Pauli string with `n` qubits, where the `i`-th qubit is `k` if `i` is in `ids`, otherwise `1`.
 `k` = 1 for I2, 2 for X, 3 for Y, 4 for Z.
 """
-paulistring(n, k, ids) = PauliString((i ∈ ids ? k : 1 for i in 1:n)...)
+paulistring(n::Int, k, ids) = PauliString((i ∈ ids ? k : _I(k) for i in 1:n)...)
+_I(::Int) = 1
+_I(::YaoBlocks.PauliGate) = I2
 
diff --git a/test/cliffordgroup.jl b/test/cliffordgroup.jl
index 75d1c54..0c66787 100644
--- a/test/cliffordgroup.jl
+++ b/test/cliffordgroup.jl
@@ -5,6 +5,8 @@ using TensorQEC: pauli_repr
 	m = pauli_repr(H)
 	pm = TensorQEC.to_perm_matrix(Int8, Int, m)
 	@test Matrix(pm) ≈ m
+	pm = TensorQEC.to_perm_matrix(H)
+	@test Matrix(pm) ≈ m
 
 	m = pauli_repr(ConstGate.CNOT)
 	pm = TensorQEC.to_perm_matrix(Int8, Int, m)
@@ -31,16 +33,16 @@ end
 @testset "perm_of_paulistring" begin
 	pm = TensorQEC.to_perm_matrix(Int8, Int, pauli_repr(H))
 	ps = PauliString((1, 2))
-	ps2, val = TensorQEC.perm_of_paulistring(pm, ps, [2])
+	ps2, val = TensorQEC.perm_of_paulistring(ps, [2]=>pm)
 	@test ps2 == PauliString((1, 4))
 
 	pmcn = TensorQEC.to_perm_matrix(Int8, Int, TensorQEC.pauli_repr(ConstGate.CNOT))
 	ps = PauliString((2, 1, 3, 2))
-	ps2, val = TensorQEC.perm_of_paulistring(pmcn, ps, [4, 2])
+	ps2, val = TensorQEC.perm_of_paulistring(ps, [4, 2]=>pmcn)
 	@test ps2.ids == (2, 2, 3, 2)
 
 	ps = PauliString((2, 4, 3, 2))
-	ps2, val = TensorQEC.perm_of_paulistring(pmcn, ps, [3, 2])
+	ps2, val = TensorQEC.perm_of_paulistring(ps, [3, 2]=>pmcn)
 	@test ps2.ids == (2, 3, 2, 2)
 end
 
diff --git a/test/paulibasis.jl b/test/paulibasis.jl
index 49ea78f..ff05d79 100644
--- a/test/paulibasis.jl
+++ b/test/paulibasis.jl
@@ -1,4 +1,4 @@
-using Test, TensorQEC, TensorQEC.Yao
+using Test, TensorQEC, TensorQEC.Yao, TensorQEC.LinearAlgebra
 
 @testset "pauli_basis" begin
 	@test pauli_basis(1) == PauliString.(1:4)
@@ -29,4 +29,10 @@ end
 	ps = PauliString(1,2,2)
 	qc = chain(cnot(3,3,2), cnot(3,3,1))
 	@test TensorQEC.pauli_string_map_iter(ps, qc).ids == (2,1,2)
+end
+
+@testset "yao interfaces" begin
+    @test paulistring(5, X, (2, 3)) == PauliString(I2, X, X, I2, I2)
+    @test pauli_decomposition(X) ≈ [0, 1, 0, 0]
+    @test pauli_mapping(X) ≈ Diagonal([1, 1, -1, -1])
 end
\ No newline at end of file