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.