繁体   English   中英

Haskell自定义数据类型

[英]Haskell Custom Data Type

我正在做作业,我们有一系列混合元素Char和Int。

我创建了此自定义类型:

data Element = CharToElement Char | IntToElement Int

它将CharInt转换为Element所以我可以处理它们。

我遇到的问题是我要转换回去时该怎么办?

因此,现在我做了(头数组)并返回Element该如何将Element转换为IntChar

这是针对后缀评估程序的。

感谢帮助。 谢谢。

编辑:

因此,我进行了处理,这就是我所拥有的:

data Element = ElementConstructor (Char, Int, Bool) | IntToElement Int | CharToElement Char | NIL

extractInt (_,i,_) = i
extractChar (c,_,_) = c
extractType (_,_,b) = b

stack_push :: [Element] -> Element -> [Element]
stack_push stack element = (element:stack)

stack_pop :: [Element] -> [Element]
stack_pop stack = (tail stack)

stack_top :: [Element] -> Element
stack_top stack = (head stack)

postfix_eval eqn = (postfix_eval_rec (postfix_eval_const eqn []) [])

postfix_eval_const eqn_raw eqn_conv =
    if null eqn_raw
        then NIL
    else
        if (isNumber (head eqn_raw))
            then ElementConstructor(NIL, (head eqn_raw), True):eqn_conv
        else if (isAlpha (head eqn_raw))
            then ElementConstructor((head eqn_raw), NIL, False):eqn_conv
        postfix_eval_const (tail eqn_raw) eqn_conv


operate :: Element -> Element -> Element -> Element
operate operator_char a b = 
    if operator_char == '+'
        then IntToElement ( (extractInt a) + (extractInt b) ) 
    else if operator_char == '-'
        then IntToElement ( (extractInt b) - (extractInt a) )
    else if operator_char == '*'
        then IntToElement ( (extractInt a) * (extractInt b) )
    else if operator_char == '/'
        then IntToElement ( (extractInt b) `div` (extractInt a) )
    else
        IntToElement(0)

postfix_eval_rec :: [Element] -> [Element] -> Int
postfix_eval_rec eqn stack = 
    if null eqn
        then (extractInt (stack_top stack))
    else if ( (extractType (head eqn)) )
        then (postfix_eval_rec (tail eqn) (stack_push stack (head eqn) ) )
    else
        (postfix_eval_rec (tail stack) (stack_push (stack_pop (stack_pop stack)) (operate (head eqn) (stack_top stack) (stack_top (stack_pop stack)))))

这个想法是,您输入类似:postfix_eval [1,2,3,'+',4,'+','*']的结果,并且您会以Int的形式得到答案,在这种情况下,您得到9

有很多方法可以解决此问题。 我只会提供一些一般性建议。

首先,努力仅使用全部功能-永远不会出错的功能。 特别是,在大多数惯用的Haskell代码中, headtail是不必要的,应将其视为代码气味。

此外,避免if /警卫可通过图案匹配来代替。 您确实应该习惯了,周围有不错的教程

例如,这是您的operate函数的第一次重做:

operate :: Element -> Element -> Element -> Element
operate (CharToElement '+') a b =
   IntToElement (extractInt a + extractInt b) 
operate (CharToElement '-') a b =
   IntToElement (extractInt a - extractInt b) 
operate (CharToElement '*') a b =
   IntToElement (extractInt a * extractInt b) 
operate (CharToElement '/') a b =
   IntToElement (extractInt a `div` extractInt b) 
operate _                   _ _ =
   IntToElement 0

这远非完美。 首先,为什么错误返回0 调用者无法将其与实际的空结果区分开。 其次,函数extractInt必定是局部的(或再次返回假结果):如果a代替char怎么办?

最终,已经在类型级别找到了谎言:

operate :: Element -> Element -> Element -> Element

这种类型的确存在:我们并非总是对所有输入都有结果Element 我们想对错误建模。 这更诚实:

operate :: Element -> Element -> Element -> Maybe Element

并且可以通过模式匹配再次实现:

operate :: Element -> Element -> Element -> Maybe Element
operate (CharToElement '+') (IntToElement a) (IntToElement b) =
   Just $ IntToElement $ a + b
operate (CharToElement '-') (IntToElement a) (IntToElement b) =
   Just $ IntToElement $ a - b
operate (CharToElement '*') (IntToElement a) (IntToElement b) =
   Just $ IntToElement $ a * b
operate (CharToElement '/') (IntToElement a) (IntToElement b) =
   Just $ IntToElement $ a `div` b
operate _                   _                _                =
   Nothing

瞧,不需要危险的extract功能。 当输入不是整数时,由于第一个匹配失败,我们只返回Nothing

这可能会觉得不太方便,因为现在我们需要在代码的其余部分中处理Maybe Element ,而该代码不再收到要使用的简单Element 但这就是重点! 代码的其余部分需要处理可能的错误,因此也必须在此处执行错误处理。 Maybe Element类型迫使我们这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM