Haskell案例的语法较短?

Ara*_*yan 4 haskell

说我有这样的傻事:

data SomeType
    = Unary Int
    | Associative SomeType
    | Binary SomeType SomeType

some_func :: SomeType -> Int
some_func s =
    case s of
        Unary n -> n
        Associative s1 -> some_func s1
        Binary s1 s2 -> some_func s1 + some_func s2
Run Code Online (Sandbox Code Playgroud)

这里some_func将查看给定SomeType中的所有SomeTypes,并总结所有Unary数据构造函数的Ints.SomeType是递归数据类型.

在这些模式匹配中我正在重复some_func s1.有没有办法使用@,when,let或其他任何东西sf1 = some_func s1在两者中声明和使用它?像这样的东西:

data SomeType
    = Unary Int
    | Associative SomeType
    | Binary SomeType SomeType

some_func :: SomeType -> Int
some_func s =
    case s of
        Unary n -> n
        Associative s1 -> sf1
        Binary s1 s2 -> sf1 + sf2
        where
            sf1 = some_func s1
            sf2 = some_func s2
Run Code Online (Sandbox Code Playgroud)

这里的问题是s1和s2仅在块之后已知,->并且无法计算sf1.

phy*_*1an 7

这不回答问题但可能解决问题:

{-# LANGUAGE DeriveFoldable #-}
module SomeType where
import Data.Foldable as F

data SomeType a
    = Unary a
    | Associative (SomeType a)
    | Binary (SomeType a) (SomeType a)
      deriving (Foldable)

some_func :: SomeType Int -> Int
some_func = F.foldl1 (+)
Run Code Online (Sandbox Code Playgroud)


huo*_*uon 5

答案是否定的:在s1Associative是不同s1Binary.它们具有相同名称的事实是分散注意力的,因为它们存在于不同的环境中.

我想你可以通过使用帮助器保存一些输入,但这并没有真正帮助封装重复的逻辑:

some_func :: SomeType -> Int
some_func s = go s
  where go (Unary n) = n
        go (Associative s1) = go s1
        go (Binary s1 s2) = go s1 + go s2
Run Code Online (Sandbox Code Playgroud)


Dan*_*ton 5

滥用记录语法!

data SomeType
    = Unary { u :: Int }
    | Associative { s1 :: SomeType }
    | Binary { s1, s2 :: SomeType }

someFunc :: SomeType -> Int
someFunc s = case s of
    Unary{}       -> u s
    Associative{} -> sf1
    Binary{}      -> sf1 + sf2
  where
    sf1 = someFunc (s1 s)
    sf2 = someFunc (s2 s)
Run Code Online (Sandbox Code Playgroud)

请注意,允许相同类型的不同构造函数在其记录中具有相同的命名字段.sf2如果你走下Associative分行,懒惰会阻止你犯错误.