访问自定义数据类型 - Lambda函数应用程序顺序

时间:2018-05-26 13:38:19

标签: haskell lambda types

得到了这个:

data Cmd = PushK Int | Pop | Push Int
         deriving (Eq,Show)

type StackProgram = [Cmd]

问题: 如何访问Int的{​​{1}}值?

PushK

任何人都有解决方案吗?

2 个答案:

答案 0 :(得分:4)

使用模式匹配或通过定义记录语法(在这种情况下Haskell自己生成getter)来从数据构造函数中取出值。

模式匹配

由于此类型定义为记录,因此我们必须使用模式匹配:

getK :: Cmd -> Int
getK (PushK x) = x
-- ...

可能你需要处理另一个数据构造函数的情况。

我们也可以使用lambda表达式执行此模式匹配:

(\(PushK x) -> x) (PushK 5)

记录

我们还可以将命令定义为记录:

data Cmd = PushK { k :: Int } | Pop | Push { p :: Int } deriving (Eq,Show)

现在Haskell自动生成了两个函数k :: Cmd -> Intp :: Cmd -> Int,所以在这种情况下我们可以写:

k (PushK 5)

将返回5

为什么(\_ x -> x) PushK 5会返回5

在Haskell中,函数是一等公民。这意味着您可以将函数作为参数传递,并将其作为结果返回。你在这里构建了一个Cmd

实际上PushK是一个数据构造函数和一个函数(类型为Int -> Cmd),因此你用两个调用了lambda表达式参数:第一个是pushK,第二个是5。您只需省略第一个参数,然后重新调整第二个x

但它因此得出:

   (\y x -> x) PushK 5
=  ((\y -> (\x -> x)) PushK) 5    -- (more verbose version)
-> (\x -> x) 5
-> 5

答案 1 :(得分:1)

您可能希望定义一个 catamorphism 来解构任意Cmd值。

cmdCata :: (Int -> a)  -- Function to apply to x in (PushK x)
        -> a           -- Value to replace Pop
        -> (Int -> a)  -- Function to apply to x in (Push x)
        -> Cmd         -- The value to deconstruct
        -> a           -- The result
cmdCata f _ _ (PushK x) = f x
cmdCata _ x _ Pop       = x
cmdCata _ _ f (Push x)  = f x

它需要两个函数和一个默认值(对于Pop)将任何 Cmd值转换为a类型的值。以下内容提取PushKPush包含的值,并使用Just对其进行重新处理(PushK的函数执行一些额外的工作,以显示{{1}之间的差异}和PushK),并将Push替换为Pop

Nothing

或者,如果您只想要一个整数,> cmdCata (Just . (+3)) Nothing Just (PushK 5) Just 8 -- 5 + 3 > cmdCata (Just . (+3)) Nothing Just Pop Nothing > cmdCata (Just . (+3)) Nothing Just (Push 20) Just 20 的默认值就可以了:

Pop

> cmdCata id 0 id (PushK 5) 5 > cmdCata id 0 id Pop 0 > cmdcata id 0 id (Push 3) 3 cmdCata进行比较,并考虑可以为Data.Maybe.maybe类型定义与Data.Maybe.fromJustData.Maybe.catMaybes等类似的功能。< / p>