В haskell тип возврата функции может зависеть только от типа ее аргументов и, в случае функций с полиморфными типами возврата, от того, как используется возвращаемое значение. В частности, тип возвращаемого значения функции не может зависеть от значения аргумента.
Другими словами: вы не можете делать то, что хотите напрямую. В случаях, когда вы хотите вернуть один из двух типов, вы можете обычно использовать тип Either a b
, который определен как data Either a b = Left a | Right b
, что позволяет вам возвращать значение типа a
, заключенное в Left
или введите b
, завернутый в Right
. Затем вы можете использовать сопоставление с образцом, чтобы получить значение безопасным для типа способом.
Однако, так как в этом случае тип для b
должен быть бесконечным, это не работает, и вы должны определить для этого свой собственный тип оболочки. Вот так:
data MyResult = Str String | Fun ( () -> MyResult)
foo 0 = Str "done"
foo x = Fun (\ () -> foo (x-1))
foo
теперь имеет тип Num a => a -> MyResult
. Однако каждый раз, когда вы вызываете foo
, вы должны выполнить сопоставление с образцом, чтобы увидеть, вернули ли вы Str со строкой внутри или Fun с функцией внутри.
Также обратите внимание, что если вы хотите вернуть функцию, а не значение, чтобы задержать выполнение, в haskell это не имеет смысла, потому что это лениво и вещи обычно не оцениваются до их использования. *