Что вы делаете здесь более или менее эквивалентно следующему:
rfib (last:last':rest) = let new = last + last' in rfib (new:last:last':rest)
который пытается создать числа в обратном порядке «лениво». (Приказ действительно не имеет значения, я просто сделал это в обратном порядке, чтобы избавиться от отвлекающих (++) и last2).
Но дело в том, что вы никогда не вычислите список, как скажет вам специалист по проверке типа. Например, происходит некорректно все хорошо напечатал:
res1 = (take 10 . rfib) [1,0] :: [Int]
res2 = (take 10 . snd . rfib) [1,0] :: [Int]
res3 = (take 10 . snd . snd . rfib) [1,0] :: [Int]
res4 = "foo" == rfib [1,0]
Иногда это хорошая идея не писать аннотации, вы знаете. Тогда вы увидите, был сделан вывод, что-то вроде этого:
rfib :: Num a => [a] -> b
, которая соответствует близко к основному типу вашей Foo ':
fib' :: Num a => State [a] b
И этот тип вы должны сделать немного подумать. В случае с rfib
он сообщает, что из ниоткуда вы создаете значение любого типа, который вы хотите, здесь называется b
. И это синоним «нет такого значения». Как и в случае head []
или unJust Nothing
или error "Bottom"
, любая попытка все же вычислить это значение должна расходиться.
Вопросы различаются, когда переменная нового типа, которая появляется в результате, «защищена» конструктором типа. Тогда то, что произойдет, будет зависеть от типа, конструктор которого применяется. В его нынешнем виде он работает с Writer, но не с государством. Тем не менее, такой неожиданный тип должен заставлять думать об этом.
Не совсем верно. Если вы возьмете его рекурсивный, бесконечный код, но поместите его в монаду-писателю, чтобы получить что-то типа 'fib [0,1] :: MonadWriter [Int] m => mb', тогда' возьмите 10 $ execWriter (fib [0, 1]) 'работает отлично, несмотря на' b' в возвращаемом типе. Таким образом, его общая попытка была не так разбита, как вы предполагаете, это была просто неправильная монада. –
Это совсем другое, @JoachimBreitner, потому что тогда тип 'm' появляется слева от стрелки => и, следовательно, не выходит из ниоткуда. Понятно, что новая переменная типа, защищенная конструктором, не сигнализирует о неопределенности, как в «Nothing :: Maybe u', а также« Monad m => m u' просто отлично. – Ingo
В какой-то момент вы говорите, что список никогда не вычисляется. Предположим, я был тем, кто писал 'rfib'. Давайте также предположим, что я беру один последний взгляд на тело 'rfib', чтобы подтвердить, что я написал, правильно, прежде чем перейти в подсказку ghci для проверки' rfib'. Теперь, не могли бы вы рассказать мне, какая часть информации заставила бы меня понять, что вычисление rfib никогда не сходится? – Jay