是否可以使用您自己的数据类型来模拟函数?

2023-11-27

是否可以使用您自己的数据类型和某些 GHC 扩展来模拟函数?我想做的是例如

(想象的语法)

data MyFunc = MyFunc String (Int->Int)

instance (Int->Int) MyFunc where
    ($) (MyFunc _ f) i = f i

inc = MyFunc "increment" (1+)

test = inc 1

IE。带有一些元信息并且可以进行模式匹配的数据,但仍然可以像常规函数一样调用。现在,我知道我可以定义自己的中缀运算符,例如$$并打电话inc $$ 1,但是能够使用常规函数调用语法在嵌入式 DSL 中将非常有用。


是的,可以在有限的范围内做到这一点。

但首先我们需要

{-# LANGUAGE Rank2Types #-}

让我们定义一下

data M a b = M { name :: Int -> String -> String, eval :: a -> b }

我正在为您的名字添加更多结构,以便我可以获得更好的演出支持。 ;)

然后我们定义一个类:

class Magic m where
    magic :: M a b -> m a b

instance Magic M where
    magic = id

instance Magic (->) where
    magic (M _ f) = f

现在,考虑类型:

type MyFunc a b = forall m. Magic m => m a b

结果类型为magic或者是(a -> b) or a M a b.

所以它可以作为成员使用MyFunc。现在,这种类型有点令人不满意,因为您无法在其上分派实例,但这确实意味着

inc :: MyFunc Int Int
inc = magic (M (const (showString "inc")) (+1))

test :: Int
test = inc 1

工作得很好。

我们甚至可以用一种相当不错的方式来展示它们。即使我们不能使用 show onMyFunc,我们可以将其定义为M.

instance Show (M a b) where
    showsPrec d (M s _) = s d

然后我们可以创建一个可以应用的函数M a b(并且通过扩展任何MyFunc)得到一个M a b.

m :: M a b -> M a b
m = id

我们可以定义一个特殊的组合器来显示MyFuncs:

showM :: MyFunc a b -> String
showM f = show (m f)

然后我们就可以玩了。我们可以定义MyFuncs.

infixr 9 .#
(.#) :: MyFunc b c -> MyFunc a b -> MyFunc a c
f .# g = magic (M 
    (\d -> showParen (d > 9) $ showsPrec 10 (m f) . 
                               showString " . " . 
                               showsPrec 9 (m g)) 
    (f . g))

inc2 :: MyFunc Int Int
inc2 = inc .# inc

test2 :: Int
test2 = inc2 1

bar, baz :: String
bar = showM inc
baz = showM inc2

而且因为我给了名称足够的结构,我们甚至可以为更复杂的组合得到正确的括号,而没有不必要的括号。

*Main> showM $ inc2 .# inc
"(inc . inc) . inc"

*Main> showM $ inc .# inc2
"inc . inc . inc"

但请记住,您将无法为MyFunc,因为它只能是一个type,而不是一个newtype。为了定义实例,您必须定义它们M,然后使用m转换为该类型,以便隐式调度有一个可以抓住的类型。

由于等级 2 类型,如果您在本地上下文中大量使用这些,您可能还需要打开NoMonoLocalBinds and/or NoMonomorphismRestriction.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以使用您自己的数据类型来模拟函数? 的相关文章

  • 为什么我不能将 Int 类型与 a 类型匹配

    哈斯克尔新手在这里 我在这里尝试做的事情的一个过于简单的例子 test Int gt a test i i Couldn t match expected type a with actual type Int a is a rigid t
  • Repa 数组上的并行 mapM

    在我最近的work https github com bgamari mixture model with Gibbs sampling 我一直在充分利用RVar http hackage haskell org packages arch
  • 用纯函数式语言保持状态

    我正在尝试弄清楚如何执行以下操作 假设您正在开发直流电机的控制器 您希望让它以用户设置的特定速度旋转 def set point ref sp 90 while true let curr read speed controller set
  • 检查 Perl 函数参数值得吗?

    有很多关于MooseX 方法 签名 http search cpan org perldoc MooseX Method Signatures甚至在此之前 诸如参数 验证 http search cpan org perldoc Param
  • 计算出类型索引的自由 monad 的细节

    我一直在使用免费的 monad 来构建 DSL 作为语言的一部分 有一个input命令 目标是在类型级别反映输入原语期望的类型 以提高安全性 例如 我希望能够编写以下程序 concat Action String String concat
  • MySQL 的 TEXT 类型的 Oracle 等效项

    Oracle 是否有与 MySQL 等效的列类型TEXT type 如果不是 那么通常如何存储较大的文本块 BLOB varchar 32767 如果重要的话 它是通过 PHP 访问 Oracle 10 历史背景是非常受欢迎的 Oracle
  • 将“C# 友好类型”名称转换为实际类型:“int” => typeof(int)

    我想得到一个System Type给定一个string指定 原始 类型C 友好名称 基本上与 C 编译器读取 C 源代码时的方式相同 我觉得描述我所追求的最好方式是单元测试的形式 我希望存在一种通用技术 可以使以下所有断言通过 而不是尝试对
  • 如何计算函数被调用的次数,FP方式

    我目前正在通过SICP http mitpress mit edu sicp 与哈斯克尔 练习 1 15 询问一个函数被调用了多少次 这个想法可能是您应该使用替换方法 但我想知道如何在代码中执行此操作 在命令式语言中 我们可以保留一个全局变
  • enumFromTo 如何工作?

    我无法将号码添加到Char 以下内容将无法编译 a 1 但是 a z 成功创建一个字符串 其中每个字符值都会递增 有没有一个特殊的函数可以增加Char 我知道我能做到chr ord c 1 如何 a z 或底层enumFromTo函数增加结
  • 我可以在程序内更改堆栈大小限制吗?

    我可以通过传递配置 GHC 编译的 Haskell 程序的最大堆栈大小 RTS Kn到它 在哪里n是某个数字 有没有办法在程序内更改此设置 我想对各种函数的堆栈消耗进行基准测试 因此尝试在各种限制下运行它 捕获StackOverflow例外
  • PHP instanceof 对于 true 条件返回 false

    我完全困惑为什么 php 的instanceof当以下情况时 运算符坚持认为此处的 LVALUE 不是已定义类的实例get class说是的 class WhereIn public function construct args echo
  • 如何检查字符串是否为类型[重复]

    这个问题在这里已经有答案了 我有类型 export type PermissionType creator editor viewer 在运行时 如何检查变量 userInput 是否实际上是上述类型之一 let userInput foo
  • 在 Haskell 中使用 Maybe 类型

    我正在尝试利用 Haskell 中的 Maybe 类型 我有一个查找返回 Maybe 的键 值元组 如何访问 Maybe 包装的数据 例如 我想将 Maybe 包含的整数与另一个整数相加 或者 您可以进行模式匹配 case maybeVal
  • 不明确的类型变量

    相关我之前关于遍历数据结构的问题 https stackoverflow com questions 1855371 avoiding boilerplate when dealing with many unrelated types 当
  • 为什么在 haskell 中不带括号不可能进行负数相乘

    乘法5 3在 haskell gchi 中给了我一个错误 但乘以5 3 工作正常 为什么需要括号 ghci GHCi version 7 4 1 http www haskell org ghc for help Loading packa
  • 优化计算 200 万以下所有素数总和的 Haskell 代码

    欧拉计划中的问题 10 我在那里看到了一些讨论 但仅限于 C 我用下面的代码来计算 print sum sieve 2 2000000 where sieve sieve x xs x sieve filter 0 mod x xs 需要很
  • 数据记录的类约束

    我有一个data type data BuildException a KillBuild JobID a Stage FailBuild JobID a Stage CancelBuild JobID a Stage StopBuild
  • C++ 获取成员函数的类型(返回类型和签名),不带成员函数的“const”限定符

    是否可以在没有成员函数的 const 限定符的情况下获取成员函数的类型 返回类型和签名 到目前为止 我尝试使用 decltype T 和 std remove const std decay Example void Func std st
  • Haskell 中的纯函数是否有可能改变变量的本地副本?

    Haskell 中的纯函数是否有可能改变变量的本地副本 就像 clojure 中提到的那样函数式编程是一个骗局 http swannodette github io 2013 06 10 porting notchs minecraft d
  • 如何在 Haskell 中处理这个简单的 IO 异常

    全部处理 在下面的代码中 getDirectoryContents dir可能会失败 例如dir可能不存在 如何捕获这个并向用户抛出有意义的消息 我知道 IO 异常处理已经被问过很多次了 但我仍然找不到一个简单的方法来做到这一点 walk

随机推荐

  • 如何在 django 中验证 json 对象

    我正在使用 AJAX 向 django 视图提交 JSON JSON 如下所示 code 9910203040 required name Abc required payments amount 300 required name efg
  • winform 友好的类名

    我有一个 C winform 应用程序 当使用间谍 时 它给出 WindowsForms10 Window 8 app 0 33c0d9d 作为类名 有没有办法将其更改为更友好的内容 没有 最后一个十六进制数字是拥有该窗口的 AppDoma
  • 如何在 vim 中删除下一个字符(不是当前字符!)?

    我经常发现自己需要删除光标后面的字符 而不是当前字符 在 vim 的正常模式下执行此操作的最短方法是什么 lx会成功 或者lxh如果您想将光标返回到原始位置 它只是向前移动光标并删除其下方的字符 如果这还不够短 您可以将其映射到单个按键 m
  • Linux集群,如何“仅仅”锁定一个文件?

    在 Bash 中 我试图使函数 getLock 与不同的锁名称一起使用 function getLock getLock FILE 1 getLock OP 2 case getLock OP in LOCK UN flock u getL
  • 如何表示当前英国时间?

    我在服务器和客户端之间转换日期时遇到问题 两者都在德国运行 客户端计算机上的区域设置可以设置为英国或德国 我从服务器收到一个 CET 格式的日期 我需要在 UI 上将此时间表示为英国时间 例如 从服务器收到的时间 如 01 07 2010
  • Jenkins/fastlane - 没有找到本地代码签名身份

    我在使用 Jenkins 的 fastlane 时遇到问题 在终端中运行此命令有效fastlane provide crashlytics build testing false check xcode false env xxx 但是詹金
  • C OpenMP 并行快速排序

    在 C 中使用 openMP 时 我再次陷入困境 这次我尝试实现并行快速排序 Code include
  • 如何在 PHP 中将日期加 1(日/年)?

    我有一个日期存储在数组中 this gt lines uDate 日期的格式不固定 我可以这样改变 define DATETIME FORMAT y m d H i 如何将我的 uDate 添加一定的天数或年数 我的问题与此相关 将日期增加
  • 如何隐藏一些 Eclipse 自动完成结果[重复]

    这个问题在这里已经有答案了 我正在 Eclipse 3 6 中开发 Wicket 应用程序 有没有办法阻止 Eclipse 自动完成中的某些包 以便我看不到对同名的不需要的 AWT 类的建议 我想看看org apache wicket结果如
  • 使用 ANT 编译 JavaFX 代码

    我的系统上安装了以下内容 Java version 1 7 0 09 JavaFX 2 0 SDK NetBeans 7 2 1 当我尝试使用 ANT 编译代码时 它显示错误消息 Could not load definitions fro
  • jquery ui tabs 主要风格变化

    我正在使用 jquery UI 选项卡 我需要主要更改它的样式 我需要重新调整背景图像 边框 几乎所有内容 我需要它看起来最小 而不是像它是独立的 最好的方法是什么 然而 我需要使用日历小部件的默认 UI 样式 该样式位于同一页面上 我做了
  • 我如何在 JQuery 中解析这个 JSON 对象? [复制]

    这个问题在这里已经有答案了 我有一个 JSON 对象 它没有给定三个值的键 每个值都是一个数组 我想解析它们 我怎样才能在 JQuery 中做到这一点 cid 3 pid 0 nid 12 uid 4 subject test2 hostn
  • 我应该在 Elixir Phoenix 的控制器或模型中使用 Ecto.Repo 吗?

    对于控制器中的一些查询Phoenix 我有两个计划 Plan 1 defmodule Demo UserController do def index do This is just for example The point is Rep
  • 为什么在 Akka Dispatcher 上启动时,Futures in Futures 会按顺序运行

    当我们尝试从参与者的接收方法中启动多个 future 时 我们观察到了奇怪的行为 如果我们使用配置的调度程序作为 ExecutionContext 则 futures 将在同一线程上按顺序运行 如果我们使用 ExecutionContext
  • createObjectURL 错误:`参数必须是 Blob 的实例。收到 Blob 的实例`

    我有一条快速路线 其中包含以下内容 let result await fetch http someurl result await result blob console log result const img URL createOb
  • MySQL 全文停用词基本原理

    我目前正在尝试为我的网站开发一个基本的全文搜索 我注意到某些单词 例如 regarding 被列为 MySQL 全文搜索的停用词 现在这并没有太困扰我 因为搜索特定新闻项目的人不一定会使用 关于 一词进行搜索 但我当然不能代表所有人 然而
  • 如何在没有 web.xml 的情况下以编程方式配置

    除了使用的方法之外 还有其他方法可以配置上下文参数吗web xml就像下面的例子一样
  • 删除引用以帮助 GC 是一个好习惯吗?

    我想知道您是否认为删除引用是一个好习惯 将它们设置为null 到对象以帮助 Java 垃圾收集器 例如 假设您有一个包含两个字段的类 其中一个字段非常消耗内存 如果您知道只需要它进行特定处理 则可以在之后立即将其置空以帮助 GC 假设我确实
  • 如何在docker容器内使用php artisan服务?

    我使用 dockerfile 创建一个 php composer 图像 FROM php 7 RUN apt get update RUN apt get install curl RUN curl sS https getcomposer
  • 是否可以使用您自己的数据类型来模拟函数?

    是否可以使用您自己的数据类型和某些 GHC 扩展来模拟函数 我想做的是例如 想象的语法 data MyFunc MyFunc String Int gt Int instance Int gt Int MyFunc where MyFunc