gpt4 book ai didi

haskell - Purescript:模式匹配通配符数据构造函数

转载 作者:行者123 更新时间:2023-12-02 15:50:12 26 4
gpt4 key购买 nike

虽然这个例子是人为的,但如果忽略数据构造函数,为什么我不能使用通配符模式?

module Main where

import Prelude
import Control.Monad.Eff.Console (log)

data Person = Amy { name :: String } | George { name :: String }

--Implementations Options Below

main = log $ personToString $ George { name: "George" }

没有错误

personToString :: Person -> String
personToString (Amy { name: n }) = n
personToString (George { name: n }) = n

错误

personToString :: Person -> String
personToString (_ { name: n }) = n

http://try.purescript.org/?session=a1503b9a-0546-7832-39b0-6321a89ef2e3

Unable to parse module:
unexpected {
expecting ::, operator or )

最佳答案

我不确定为什么编译器无法推断出两个 sum 类型都有 { name::String } 作为参数。我认为编译器现在还不能做到这一点,而且我不确定这是否可能。

话虽如此,有一些方法可以内省(introspection)您使用的类型,并且您可以定义 personToString 函数,以便它可以在您的 Person 类型上工作。请记住,这是深入研究该语言的更高级领域,这对我来说也是一个新领域。这可能远远超出了您的问题,但可能对其他人有帮助,并且很高兴知道什么是可能的。

首先,让我们为“有名称的类型”定义一个类型类。

class DoesHaveName a where
getName :: a -> String

现在我们需要检查 Person 类型的结构。为此,我们可以使用 purescript-generics-rep包裹。首先,我们将告诉编译器检查数据类型并创建它的通用表示形式。我们将为 Person 类型创建一个 Generic 实例。

import Data.Generic.Rep (class Generic)

derive instance genericPerson :: Generic Person _

通过查看 Data.Generic.Rep 中的构造函数,我们可以看到表示类型的所有不同方式。 ,我们可以使用 fromPerson 转换为该结构。 .

import Data.Generic.Rep (class Generic, from)

personToString :: Person -> String
personToString a = getName (from a)

现在我们必须为任何接受 { name::String } 的单参数构造函数创建一个 DoesHaveName 实例。

import Data.Generic.Rep (class Generic, to, from, Sum(..), Rec(..), NoConstructors, Constructor(..), Field(..))
import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol)

instance doesHaveNameConstructor
:: (IsSymbol t0, IsSymbol t1)
=> DoesHaveName (Constructor t0 (Rec (Field t1 String))) where
getName (Constructor (Rec (Field c))) =
case (reflectSymbol (SProxy :: SProxy t1)) of
"name" -> c
_ -> "NoName"

有很多值得思考的地方。我会尽力将其分解。 t0t1 是符号 - 因此它们是您编写的文字代码的一部分。在本例中,t0 是 Sum 类型构造函数的名称(Amy 或 George)。 t1 是记录的标签(在您的示例中它将是“name”)。因此,我们使用 reflectSymbol 将符号转换为我们可以匹配的字符串。如果标签是“name”,那么我们将返回字段内的值,否则我们将返回“NoName”。

我们需要做的最后一件事是为 Sum 类型结构创建一个 DoesHaveName 实例。 Sum 类型包含构造函数,因此该实例基本上只是处理外部结构并委托(delegate)给我们上面定义的实例。

instance doesHaveNameSum
:: (DoesHaveName a, DoesHaveName b)
=> DoesHaveName (Sum a b) where
getName (Inl a) = getName a
getName (Inr b) = getName b

现在我们可以记录各种人的名字...

data Person
= Amy { name :: String }
| George { name :: String }
| Jim { name :: String }


-- Logs "amy"
log $ personToString (Amy { name: "amy" }

-- Logs "george"
log $ personToString (George { name: "george" }

-- Logs "jim"
log $ personToString (Jim { name: "jim" }

演示:http://try.purescript.org/?gist=2fc95ad13963e96dd2a49b41f5703e21

关于haskell - Purescript:模式匹配通配符数据构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46270237/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com