English 中文(简体)
甲醇类型数据构造者的“Pattern配对”
原标题:"Pattern matching" of algebraic type data constructors

让我们考虑一种数据类型,其中有许多构造者:

data T = Alpha Int | Beta Int | Gamma Int Int | Delta Int

我想写一个功能,检查是否与同一建筑商生产两种价值:

sameK (Alpha _) (Alpha _) = True
sameK (Beta _) (Beta _) = True
sameK (Gamma _ _) (Gamma _ _) = True
sameK _ _ = False

维护<条码>sameK不是很幸运的,因此无法轻易加以核对。 例如,如果在<代码>T上添加新的构件,就很容易忘记更新<代码>sameK。 举一个例子:

-- it’s easy to forget:
-- sameK (Delta _) (Delta _) = True

问题是如何避免在<代码>sameK上的碎块? 或如何确保对<代码>T的构件进行核对?


<>m>. 我发现的工作是,为每个建筑商分别使用数据类型,得出<代码>Data.Typeable,并宣布一个共同类型类别,但我不喜欢这一解决办法,因为这个办法远不易读,而只是为我设计的简单的图书馆类型:。

{-# LANGUAGE DeriveDataTypeable #-}

import Data.Typeable

class Tlike t where
  value :: t -> t
  value = id

data Alpha = Alpha Int deriving Typeable
data Beta = Beta Int deriving Typeable
data Gamma = Gamma Int Int deriving Typeable
data Delta = Delta Int deriving Typeable

instance Tlike Alpha
instance Tlike Beta
instance Tlike Gamma
instance Tlike Delta

sameK :: (Tlike t, Typeable t, Tlike t , Typeable t ) => t -> t  -> Bool
sameK a b = typeOf a == typeOf b
最佳回答

查阅数据。 数据模块,toConstr,特别是功能。 除{-# LANGUAGE DeriveDataypeable #-}外,还将使您获得一线解决方案,该解决方案针对的是Data.Data的任何类型。 你们不需要把所有海关都包括在内!

如果出于某种原因(与Hugs有过问),这不是一种选择,那么,这里就是一个非常丑恶和非常缓慢的黑板。 它只有在以下情况下才会发挥作用:<代码>Show>(例如,通过deriving (Show)----------------------------------------------

constrT :: T -> String
constrT = head . words . show
sameK x y = constrT x == constrT y

www.un.org/spanish/ecosoc 得到<代码>外层构造者的扼杀性表述。 T 显示其价值,把它打成言语,然后首先取。 我给出了明确的签字类型,这样你就不希望将其用于其他类型(并逃避垄断限制)。

www.un.org/Depts/DGACM/index_spanish.htm 一些明显的不利之处:。

  • This breaks horribly when your type has infix constructors (such as data T2 = Eta Int | T2 :^: T2)
  • If some of your constructors have a shared prefix, this is going to get slower, as a larger part of the strings has to be compared.
  • Doesn t work on types with a custom show, such as many library types.

这就是说的:is。 Haskell 98. 但是,这只是我可以说的一点!

问题回答

另一种可能的办法:

sameK x y = f x == f y
  where f (Alpha _)   = 0
        f (Beta _)    = 1
        f (Gamma _ _) = 2
        -- runtime error when Delta value encountered

时间错误并不理想,但比无声地给出错误答案更好。

你们需要使用像Schrap You Boilerplate这样的普通图书馆,或者一般这样做。

如果你不希望如此高压,你就可以利用Dave Hinton的解决方案以及空洞的记录捷径:

...
where f (Alpha {}) = 0
      f (Beta {}) = 1
      f (Gamma {}) = 2

因此,你们不必知道每个建筑商拥有多少动力。 但是,这显然仍需要做些什么。

在某些情况下,“Scrap You Boilerplate”图书馆将提供帮助。

http://www.haskell.org/haskellwiki/Scrap_your_boilerplate

你可以肯定地利用通用物来消除碎片。 你的守则是我(和许多其他人<>>/m>的原因。 使用<代码>_上层野心。 虽然它不愿意列举所有案件,但它不像处理这些案件那样麻烦。

在这一令人高兴的例子中,我不仅会利用Dave Hinton的解决方案,而且会把INLINE的一纸rag放在辅助职能f上。





相关问题
Euler Problem in Haskell -- Can Someone Spot My Error

I m trying my hand at Euler Problem 4 in Haskell. It asks for that largest palindrome formed by multiplying two three-digit numbers. The problem was simple enough, and I thought my Haskell-fu was up ...

How does foldr work?

Can anybody explain how does foldr work? Take these examples: Prelude> foldr (-) 54 [10, 11] 53 Prelude> foldr (x y -> (x+y)/2) 54 [12, 4, 10, 6] 12.0 I am confused about these executions....

Efficient queue in Haskell

How can I efficiently implement a list data structure where I can have 2 views to the head and end of the list, that always point to a head a tail of a list without expensive calls to reverse. i.e: ...

Problem detecting cyclic numbers in Haskell

I am doing problem 61 at project Euler and came up with the following code (to test the case they give): p3 n = n*(n+1) `div` 2 p4 n = n*n p5 n = n*(3*n -1) `div` 2 p6 n = n*(2*n -1) p7 n = n*(5*n -3)...

Ways to get the middle of a list in Haskell?

I ve just started learning about Functional Programming, using Haskel. I m slowly getting through Erik Meijer s lectures on Channel 9 (I ve watched the first 4 so far) and in the 4th video Erik ...

haskell grouping problem

group :: Ord a => [(a, [b])] -> [(a, [b])] I want to look up all pairs that have the same fst, and merge them, by appending all the list of bs together where they have the same a and discarding ...

Closest equivalent to subprocess.communicate in Haskell

I want to do a popen() / python s subprocess.communicate from Haskell - start a program, give it stdin, and get its stdout/stderr. What s the most direct / Haskellish way to do this?

热门标签