Haskell中如何编写接收值与类型参数的函数?
Great question! In Haskell, we don't have direct syntax for passing type parameters like your pseudocode f x T, but we can achieve exactly what you want using the TypeApplications extension, paired with your existing Transform type class. Let's break this down step by step:
We'll use GHC's TypeApplications extension to explicitly specify the target type T, while letting Haskell's type inference handle the rest—no need to explicitly annotate the entire expression's type.
1. Enable Required Extensions
First, add these extensions at the top of your file (they're standard, well-supported GHC extensions):
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE ExplicitForAll #-} -- Optional, but makes type parameter order explicit
2. Define the Transform Class and Instances
Let's start with your type class plus some example instances to demonstrate:
class Transform a b where transform :: a -> b -- Example 1: Convert Int to String instance Transform Int String where transform = show -- Example 2: Convert Int to Bool (check if positive) instance Transform Int Bool where transform = (> 0) -- Example 3: Convert String to Int instance Transform String Int where transform = read
3. Implement Function f
Your function f is essentially a wrapper for transform (you could even use transform directly if you prefer). The key is to define its type signature to let us explicitly specify the target type T:
f :: forall b a. Transform a b => a -> b f = transform
The forall b a. clarifies the order of type parameters: b is the target type (your T), and a is the type of input x.
4. Call f (Matching Your Pseudocode f x T)
In Haskell, we use the @Type syntax to pass type parameters. Your pseudocode f x T translates directly to f @T x:
-- Convert Int 5 to String (matches pseudocode `f 5 String`) stringResult = f @String 5 -- Value: "5" -- Convert Int (-3) to Bool (matches pseudocode `f (-3) Bool`) boolResult = f @Bool (-3) -- Value: False -- Convert String "42" to Int (matches pseudocode `f "42" Int`) intResult = f @Int "42" -- Value: 42
Why No Explicit Expression Type Annotation?
Haskell's type inference does the heavy lifting automatically:
- When you specify
@Stringas the target typeb, and pass an inputxof typeInt, GHC automatically finds and uses theTransform Int Stringinstance. - You never need to write something like
stringResult :: String(though you can if you want to be explicit—it's just not required).
Bonus: Let Type Inference Do All the Work
If your code context already defines the target type, you don't even need the @T syntax! For example:
-- putStrLn expects a String, so GHC infers we need the Transform Int String instance main = putStrLn (f 5)
This will automatically output "5" without any type annotations.
- Use the
TypeApplicationsextension to mimic "passing a type parameter"—your pseudocodef x Tbecomesf @T xin valid Haskell. - Haskell's type inference eliminates the need for explicit expression type annotations.
- Keep your
Transforminstances well-defined to ensure the compiler can find the correct instance without ambiguity.
内容的提问来源于stack exchange,提问作者Andrey Tyukin

