I really don't like the use of an rCTE for tasks like this, that are iterative and slow (far slower than a Tally, especially when more than a few rows). You could use a Tally and do this far faster. As a TVF, this would like like this:
CREATE FUNCTION dbo.GetChars (@String varchar(8000))
RETURNS table
AS RETURN
WITH N AS(
SELECT N
FROM(VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP (LEN(@String)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3, N N4)
SELECT SUBSTRING(@String, T.I, 1) AS C, T.I
FROM Tally T;
GO
db<>fiddle
Note, this will not work on SQL Server 2005.