是否有一个泛型函数,它接受数据结构并返回其中的所有int?

use*_*156 6 haskell generic-programming

我认为类型签名看起来像f :: a -> [Int] 输入数据data NamedPoint = NamedPoint String Int Int

data Person = Name Int Int Int
Run Code Online (Sandbox Code Playgroud)

在REPL中使用它看起来像这样:

>> let namedPoint = NamedPoint "hey" 1 2
>> let tommy = Person "Tommy" 1 2 3
>> f namedPoint
>> [1,2] 
>> f Tommy
>> [1,2,3]
Run Code Online (Sandbox Code Playgroud)

我认为这对于记录的替代方法很有用,因为当你懒得为具有大量参数的数据编写getter时.

cch*_*ers 10

这个Data班是有能力的.我发现使用它的最简单方法是templatelens包中进行遍历.这基本上允许您使用Data实例设置或获取任何内容.在ghci:

> import Data.Data
> import Control.Lens
> import Data.Data.Lens

> -- Data is a derivable class
> :set -XDeriveDataTypeable
> data NamedPoint = NamedPoint String Int Int deriving (Data, Show)
> data Person = Name String Int Int Int deriving (Data, Show)
> let namedPoint = NamedPoint "hey" 1 2
> let tommy = Name "Tommy" 1 2 3

> let ints = toListOf template :: Data a => a -> [Int]
> ints namedPoint
[1,2]
> ints tommy
[1,2,3]
Run Code Online (Sandbox Code Playgroud)

因为template是遍历,您还可以映射值(但您可能需要指定类型):

> namedPoint & template *~ (10 :: Int)
NamedPoint "hey" 10 20
> import Data.Char
> tommy & template %~ toUpper
Name "TOMMY" 1 2 3
Run Code Online (Sandbox Code Playgroud)


zeg*_*jan 9

使用您描述的类型签名功能无法实现此功能.想想这f :: a -> [Int]意味着什么:f应该是一个函数,它接受任何可能类型的值并返回一个Ints 列表.如何定义这样的功能?唯一可能的定义是它忽略参数并返回一个常量值,例如

f :: a -> [Int]
f _ = [0]
Run Code Online (Sandbox Code Playgroud)

如果你知道你a将会是什么,为什么不使用那种类型呢?像这样:

f :: NamedPoint -> [Int]
f (NamedPoint _ a b) = [a, b]
Run Code Online (Sandbox Code Playgroud)

如果你想要一些"常规"函数Int从数据类型返回所有s,一个选项是定义一个类型类

class IntContainer a where
    f :: a -> [Int]
Run Code Online (Sandbox Code Playgroud)

然后为您感兴趣的数据类型定义实例

instance IntContainer NamedPoint where
    f (NamedPoint _ a b) = [a, b]
Run Code Online (Sandbox Code Playgroud)