functional programming - Transforming functions of type `a -> b` into those of type `String -> String` in Haskell -
my intention simple. want wrap functions of type a -> b
string -> string
(so bunch of heterogeneous functions can put in list). write:
wrap :: (read a, show b) => (a -> b) -> (string -> string) wrap f = \s -> show $ f (read s :: a)
however, ghc
complaints:
could not deduce (read a1) arising use of `read' context (read a, show b) bound type signature wrap :: (read a, show b) => (a -> b) -> string -> string
i want know why piece of code won't work , kind of hacks needed achieve goal?
thanks.
your code won't work because haskell doesn't re-use or scope type variables; a
in wrap :: (read a, show b) => (a -> b) -> (string -> string)
different a
1 in read s :: a
(and they're both universally quantified). source of a1
in error message; ghc alpha-converting program to
wrap :: (read a, show b) => (a -> b) -> (string -> string) wrap f = \s -> show $ f (read s :: a1)
however, f
's argument type fixed inside wrap
, removing type annotation works fine. function becomes
wrap :: (read a, show b) => (a -> b) -> (string -> string) wrap f = \s -> show $ f (read s) -- or wrap f = show . f . read
and can use it:
ghci> map ($ "42") [wrap (+ (7 :: integer)), wrap (* (2.0 :: double))] ["49","84.0"]
note means read s
has type can't write down. in haskell 2010 (or 98), way around use function astypeof :: -> -> a
; astypeof
const
, type signature, constrains first, returned, argument of same type second. then, of course, you'd have conjure variable of type a
. following work that:
wrap :: (read a, show b) => (a -> b) -> (string -> string) wrap f = \s -> show $ f (read s `astypeof` finput) finput = undefined foutput = f finput -- still can't give type signature
in ghc, avoid this, can turn on the scopedtypevariables
extension; on, if explicitly qualify type variables forall
, they'll scoped value-level names. code become
{-# language scopedtypevariables #-} wrap :: forall b. (read a, show b) => (a -> b) -> (string -> string) wrap f = \s -> show $ f (read s :: a)
but remember, don't need type annotations @ simple example.
Comments
Post a Comment