pattern to hide function
I often have pair of functions like this:
fooInner :开发者_运维技巧: Int -> Int -> [Int] -> [Int]
fooInner 0 base accum = accum
fooInner num base accum = fooInner c base ([r] ++ accum)
where ....
foo :: Int -> Int -> [Int]
foo a b = numNotationInner a b []
I have created 'foo' to more comfortable use of function. Instead of fooInner 10 4 [] I can use foo 10 4.
Is there any way to 'hide' fooInner inside foo to limit its scope?
In this case, you could just hide the guts in a where
block:
foo :: Int -> Int -> [Int]
foo a b = fooInner a b [] where
fooInner :: Int -> Int -> [Int] -> [Int]
fooInner 0 base accum = accum
fooInner num base accum = fooInner c base ([r] ++ accum)
where ...
Though there are a couple issues you might encounter doing this:
If the implementation has multiple patterns, the
where
block will only apply to one of them:foo :: Int -> Int -> [Int] foo 0 b = fooInner 1 b [] -- fooInner not in scope foo a b = fooInner a b [] where ... define fooInner ...
Unless Haskell has some syntactic feature I don't know about, you'll have to do something like this if you still want to pattern match:
foo a b = case (a, b) of (0, b) -> fooInner 1 b [] (a, b) -> fooInner a b [] where ... define fooInner ...
I didn't test this. You might have to tinker with the whitespace to get rid of syntax errors.
If your function has polymorphic types, you may run into trouble trying to add a type signature to the inner function:
foo :: (a -> a) -> a -> [a] foo f z = loop z where -- loop :: a -> [a] -- causes a type error loop z = z : loop (f z)
The problem with the type signature
loop :: a -> [a]
is that, in its context, it doesn't truly work for alla
, just thea
corresponding to the arguments passed tofoo
. Because it's usingf
, the type is bound to thata
, meaning it can no longer work for anya
.The simple solution here is to not use a type signature. However, if you really want or even need a type signature, but adding one results in a type error, enable the
ScopedTypeVariables
extension, and do this:foo :: forall a. (a -> a) -> a -> [a] foo f z = loop z where loop :: a -> [a] loop z = z : loop (f z)
The
forall
extends the scope ofa
beyond its originating type signature to cover any type signatures appearing in the implementation. This means that inloop :: a -> [a]
,a
is bound to thea
infoo
's signature.
精彩评论