简体   繁体   English

新类型的数据构造函数中的函数定义示例

[英]Example of function definition in the data constructor of a new type

We can use type synonym for function definitions, eg 我们可以使用类型同义词来表示函数,例如

type FuncDef = Int -> Int -> Int

This avoids us writing long function definition every time. 这避免了我们每次编写长函数定义。

Use: 使用:

someFunc :: FuncDef -> Int

Instead of 代替

someFunc :: (Int -> Int -> Int) -> Int

which is more readable and less code as well. 这更易读,也更少代码。

Simple algebraic data types are straight forward and easy to do pattern matching etc, eg 简单的代数数据类型是直接的,易于进行模式匹配等,例如

data AType = X | Y | Z Int
matchType :: AType -> Bool
matchType X = ..
matchType Y = ..
matchType (Z _) = ..

As I look more into Haskell data types, I found we can have function definition in data constructor when defining new type. 当我更多地了解Haskell数据类型时,我发现在定义新类型时我们可以在数据构造函数中使用函数定义。

data MyType a b = X | Y (a -> b)

This puzzles me a bit and haven't seen many examples of this around. 这让我感到困惑,并没有看到很多这方面的例子。 In a way, the idea of high-order function where a function can take another function as argument is similar to this situation, except here it applies to data type. 在某种程度上,函数可以将另一个函数作为参数的高阶函数的想法与这种情况类似,除了它适用于数据类型。 The Haskell wiki does not say much about "high-order data type definition". Haskell维基没有多说“高阶数据类型定义”。 I realise I may be getting all these terms wrong, so please correct me, and point me to more reading. 我意识到我可能会把所有这些条款都弄错了,所以请纠正我,并指出我更多阅读。 I really want to see a concrete usage of this. 我真的希望看到具体用法。 Thanks! 谢谢!

matchMyType :: (MyType a b) -> Bool
matchMyType X = ..
matchMyType Y ?? = .. 

You might use this kind of pattern in many situations. 在许多情况下,您可能会使用这种模式。 For example, if you want a function that transforms strings in various ways, you might have a data type like this (This is just an example that demonstrates the principle - don't write code like this!): 例如,如果你想要一个以各种方式转换字符串的函数,你可能会有这样的数据类型(这只是一个演示原理的例子 - 不要写这样的代码!):

data StringTransformation =
  -- | Doesn't transform the string at all
  NoTransformation |
  -- | Takes the string and generates a suffix that should be appended
  Append (String -> String) |
  -- | Takes the string and generates a prefix that should be prepended
  Prepend (String -> String) |
  -- | Takes the string and transforms it arbitrarily to a new string
  Map (String -> String)

Then, a program that uses this might look like: 然后,使用它的程序可能如下所示:

-- | Returns 'True' if the name is male
isMaleName :: String -> Bool
isMaleName = ...

-- | Adds a title to a name, for example "John Smith" -> "Mr. John Smith"
addTitle :: StringTransformation
addTitle =
  PrependTransformation $ \ name ->
  if isMaleName name
  then "Mr. "
  else "Mrs. "

-- Applies a string transformation to a 'String'.
transformString :: StringTransformation -> String -> String
transformString NoTransformation str = str
transformString (Append f) str       = str ++ f str
transformString (Prepend f) str      = f str ++ str
transformString (Map f) str          = f str
data Thingy a b = A b
                | B (a -> b)

really :: Thingy a b -> a -> b
really (A x) _ = x              -- x :: b
really (B f) y = f y            -- f :: a -> b, y :: a, f y :: b

As CAMcCann says, there's nothing special about functions really. 正如CAMcCann所说,真正的功能并没有什么特别之处。

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

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