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

Cardano friendlyValidityRange函数的Haskell语法及传参解析

语法规则说明

你看到的写法和*偏函数(partial function)*无关,是Haskell两个核心特性加一个常规语法扩展的组合效果:

  • 柯里化(Currying):Haskell中所有多参数函数本质都是单参数函数,类型签名a -> b -> c实际等价于a -> (b -> c):函数接收第一个a类型参数后,会返回一个新的、接收b类型参数、最终返回c类型结果的函数。这就是两个参数可以"分离"传入的根本原因。
  • LambdaCase语法扩展:在文件头部启用{-# LANGUAGE LambdaCase #-}后,\case就是\param -> case param of的语法糖,不需要显式给lambda的绑定参数命名。

所以你看到的friendlyValidityRange era = \case ...写法,完全等价于下面的常规写法,没有任何特殊逻辑:

friendlyValidityRange era validityRange = case validityRange of
  ShelleyTtl ttl -> object ["time to live" .= ttl]
  (lowerBound, upperBound)
    | isLowerBoundSupported || isUpperBoundSupported -> object [ ... ]
    | otherwise -> Null
  where
    isLowerBoundSupported = isJust $ validityLowerBoundSupportedInEra era
    isUpperBoundSupported = isJust $ validityUpperBoundSupportedInEra era

等号左边先绑定第一个参数era,等号右边直接返回一个接收第二个参数(有效性范围元组)的函数,这个函数用LambdaCase对传入的第二个参数做模式匹配,where子句里可以直接访问已经绑定的era变量。


示例代码的正确实现

你之前写的示例代码问题出在模式匹配的对象搞反了:当前写法里\case匹配的是第二个传入的元组参数,但你写的Child/Adult是第一个参数Age类型的构造器,自然无法匹配。
如果要完全模仿原函数的写法,需要在文件头启用LambdaCase扩展,在LambdaCase里匹配第二个传入的体重元组,同时直接使用已经绑定的age变量,完整可运行代码如下:

{-# LANGUAGE LambdaCase #-}
module Main where

data Age = Child | Adult deriving (Eq, Show)

weightAnalyse :: Age -> (Int, Int) -> String
weightAnalyse age = \case
  -- 直接解构第二个参数传入的(Int, Int)元组
  (wMin, wMax)
    | age == Child -> "儿童适宜体重范围:" ++ show wMin ++ "kg ~ " ++ show wMax ++ "kg,建议保证每日蛋白质摄入"
    | age == Adult -> "成人适宜体重范围:" ++ show wMin ++ "kg ~ " ++ show wMax ++ "kg,建议每周保持3次以上运动"

main :: IO ()
main = do
  putStrLn $ weightAnalyse Child (30, 60)
  putStrLn $ weightAnalyse Adult (60, 130)

运行输出结果为:

儿童适宜体重范围:30kg ~ 60kg,建议保证每日蛋白质摄入
成人适宜体重范围:60kg ~ 130kg,建议每周保持3次以上运动

如果你希望在LambdaCase中直接匹配Age类型的构造器,只需要调整参数绑定顺序即可:不在等号左侧绑定age参数,让LambdaCase匹配第一个Age参数,返回的函数再接收第二个元组参数,写法如下:

weightAnalyse :: Age -> (Int, Int) -> String
weightAnalyse = \case
  Child -> \(wMin, wMax) -> "儿童适宜体重范围:" ++ show wMin ++ "kg ~ " ++ show wMax ++ "kg,建议保证每日蛋白质摄入"
  Adult -> \(wMin, wMax) -> "成人适宜体重范围:" ++ show wMin ++ "kg ~ " ++ show wMax ++ "kg,建议每周保持3次以上运动"

两种写法执行效果完全一致,只是柯里化下参数绑定的位置选择不同,没有性能或语义上的差别。

补充说明:原Cardano代码中ShelleyTtl ttl能直接作为元组位置的匹配分支,是因为代码中启用了模式同义词(PatternSynonyms)扩展,将早期Shelley时代仅支持TTL单值的特殊元组形式封装成了ShelleyTtl可匹配模式,不属于基础语法规则。

内容的提问来源于stack exchange,提问作者breeze wang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 01:01:43