You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用其他方式实现Haskell中MyData类型的ifA/ifB/ifC匹配函数?

Absolutely! There are several ways to implement those constructor-matching functions you wrote, and you’re right that the lens library has a very elegant solution for this kind of sum type manipulation. Let’s break this down step by step.

1. Simplified Vanilla Haskell (No Libraries)

Your original code is already clear and functional, but we can make it a bit more concise using lambda case syntax (requires the LambdaCase extension):

{-# LANGUAGE LambdaCase #-}

data MyData = A Int | B String | C deriving (Show)

matchA :: MyData -> Maybe Int
matchA = \case
    A i -> Just i
    _ -> Nothing

matchB :: MyData -> Maybe String
matchB = \case
    B s -> Just s
    _ -> Nothing

matchC :: MyData -> Maybe ()
matchC = \case
    C -> Just ()
    _ -> Nothing

This does exactly the same work as your original ifA/ifB/ifC functions—it’s just a more compact way to write the pattern matching logic. Your existing example1 and example2 will work perfectly if you swap in these renamed functions.

2. Using the Lens Library (Prism for Sum Types)

You’re spot-on that lens has purpose-built tools for this scenario! The key component here is a Prism—an optic designed exclusively for working with sum types (like your MyData). Prisms let you:

  • Extract a value from a specific constructor (returning Maybe if the constructor doesn’t match)
  • Construct an instance of the sum type from a value for that constructor

Step 1: Generate Prisms Automatically

First, enable the TemplateHaskell extension and import the core lens modules. We can use makePrisms to auto-generate prisms for all constructors of MyData:

{-# LANGUAGE TemplateHaskell #-}
import Control.Lens

data MyData = A Int | B String | C deriving (Show)

-- This generates prisms named _A, _B, _C automatically
makePrisms ''MyData

Step 2: Extract Values with preview

The preview function takes a prism and a value, returning Just the inner value if the constructor matches, or Nothing otherwise. This is exactly what your original functions do:

-- Equivalent to ifA
preview _A (A 42)  -- Just 42
preview _A (B "hi") -- Nothing

-- Equivalent to ifB
preview _B (B "Hello") -- Just "Hello"
preview _B C           -- Nothing

-- Equivalent to ifC
preview _C C           -- Just ()
preview _C (A 10)      -- Nothing

Step 3: Rewrite Your Examples

Your example1 and example2 can be rewritten with these prisms, and even simplified using the >=> Kleisli composition operator (from Control.Monad):

import Control.Monad ( (>=>) )

mbMult3 :: Int -> Maybe Int
mbMult3 i = Just (i * 3)

concWorld :: String -> Maybe String
concWorld str = Just (str ++ " World")

-- Original monadic bind style
example1 :: MyData -> Maybe Int
example1 v = preview _A v >>= mbMult3

-- More concise with Kleisli composition
example1' :: MyData -> Maybe Int
example1' = preview _A >=> mbMult3

example2 :: MyData -> Maybe String
example2 v = preview _B v >>= concWorld

example2' :: MyData -> Maybe String
example2' = preview _B >=> concWorld

Step 4: Manual Prism Definition (No TemplateHaskell)

If you prefer to avoid TemplateHaskell, you can define prisms manually using the prism function:

_A :: Prism' MyData Int
_A = prism A $ \case
    A i -> Right i
    x   -> Left x

_B :: Prism' MyData String
_B = prism B $ \case
    B s -> Right s
    x   -> Left x

_C :: Prism' MyData ()
_C = prism (const C) $ \case
    C -> Right ()
    x -> Left x

The prism function takes two arguments:

  1. A constructor function (e.g., A turns an Int into MyData)
  2. A matching function that returns Right the inner value if it matches, or Left the original value otherwise.

Why Use Prisms?

Beyond just extracting values, prisms unlock more powerful workflows:

  • Modify the inner value of a matching constructor with over or set
  • Combine prisms with other optics (like lenses for product types)
  • Use them with lens’s extensive combinators for complex data manipulation

内容的提问来源于stack exchange,提问作者Dulguun Otgon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:42:04