- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我定义了一个简单的代数(具体)数据类型,MyType:
data MyTpe = MyBool Bool | MyInt Int
...我正在尝试找到一种方法将任意函数(a->b)“转换”为关联的(MyType->MyType)函数,其中a和b是Bool或Int。
这完成了工作,它将 (a->b) 转换为 Maybe (MyType->MyType)(参见下面的 [1]):
import Data.Typeable
data MyTpe = MyBool Bool | MyInt Int deriving Show
liftMyType :: (Typeable a, Typeable b) => (a -> b) -> Maybe (MyTpe -> MyTpe)
liftMyType f = case castIntInt f of
Just g -> Just $ liftIntInt g
Nothing ->
case castIntBool f of
Just g -> Just $ liftIntBool g
Nothing ->
case castBoolInt f of
Just g -> Just $ liftBoolInt g
Nothing ->
case castBoolBool f of
Just g -> Just $ liftBoolBool g
Nothing -> Nothing
castIntInt :: (Typeable a, Typeable b) => (a -> b) -> Maybe (Int -> Int)
castIntInt f = cast f :: Maybe (Int -> Int)
castIntBool :: (Typeable a, Typeable b) => (a -> b) -> Maybe (Int -> Bool)
castIntBool f = cast f :: Maybe (Int -> Bool)
castBoolInt :: (Typeable a, Typeable b) => (a -> b) -> Maybe (Bool -> Int)
castBoolInt f = cast f :: Maybe (Bool -> Int)
castBoolBool :: (Typeable a, Typeable b) => (a -> b) -> Maybe (Bool -> Bool)
castBoolBool f = cast f :: Maybe (Bool -> Bool)
liftIntInt :: (Int -> Int) -> (MyTpe -> MyTpe)
liftIntInt f (MyInt x) = MyInt (f x)
liftIntBool :: (Int -> Bool) -> (MyTpe -> MyTpe)
liftIntBool f (MyInt x) = MyBool (f x)
liftBoolInt :: (Bool -> Int) -> (MyTpe -> MyTpe)
liftBoolInt f (MyBool x) = MyInt (f x)
liftBoolBool :: (Bool -> Bool) -> (MyTpe -> MyTpe)
liftBoolBool f (MyBool x) = MyBool (f x)
然而,这非常丑陋并且不能很好地扩展:如果我想以这种方式扩展 MyType 怎么办?
data MyTpe = MyBool Bool | MyInt Int | MyString String
... 或者,如果我还想将 (a1 -> a2 -> b)(其中 a1、a2 和 b 为 Bool 或 Int)转换为关联的 (MyType->MyType->MyType) 函数怎么办? ..
我的问题:有没有一种简单、更优雅、更像 Haskell 的方法来处理这个问题?
[1]:liftIntInt 函数等未在所有 MyType 元素上定义(例如,liftIntInt 未为(MyBool x) 元素定义)。该代码只是一个简化的案例示例,在现实生活中我正确地处理了这个问题。
最佳答案
您正在寻找一种类型
goal :: (a -> b) -> (MyType -> MyType)
对于 a
的一些“合适”选择和b
。这些“合适”的选择静态地称为 MyType
的定义。是静态已知的。
您正在寻找的是类型类。特别是,我们需要 MultiParamTypeClasses
编译指示
{-# LANGUAGE MultiParamTypeClasses #-}
class MapMyType a b where
liftMyType :: (a -> b) -> (MyType -> MyType)
现在是 liftMyType
的完整类型是
liftMyType :: MapMyType a b => (a -> b) -> (MyType -> MyType)
我们可以使用类型类机制来存储 liftMyType
的各种实例化让它仅在 a
时可用和b
可以解析为 liftMyType
的类型有人居住。
instance MapMyType Int Int where liftMyType f (MyInt x) = MyInt (f x)
instance MapMyType Int Bool where liftMyType f (MyInt x) = MyBool (f x)
instance MapMyType Bool Int where liftMyType f (MyBool x) = MyInt (f x)
instance MapMyType Bool Bool where liftMyType f (MyBool x) = MyBool (f x)
-- (as a side note, this is a dangerous function to instantiate since it
-- has incomplete pattern matching on its `MyType` typed argument)
现在,值得一提的是MultiParamTypeClasses
这样使用时常常会损害推理。特别是,如果我们正在查看代码片段 liftMyType a b
我们必须能够推断 a
的类型和b
自己(例如,没有从调用“向下”传递到 liftMyType
的提示的帮助),否则我们将得到一个不明确的实例编译失败。实际上,这尤其糟糕的是,如果 任一 a
我们都会遇到编译失败。或b
无法直接推断。
在许多情况下,您可能希望使用 FunctionalDependencies
来控制此问题允许在两个参数之间进行更多的“流动”推断,并减少歧义错误。
但在这种情况下,我认为这是代码异味。虽然上面的代码可以工作(需要注意注释),但它给人的感觉是一个脆弱的解决方案。
关于haskell - 从 (a->b) 到 (MyType->MyType),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27393968/
我在为自定义类型的 ObservableCollection 创建扩展方法时遇到问题。我需要创建的扩展方法是“ToAnotherType”类型(如 ToList、ToArray)。 MyPoint 示
所以基本上我有这个方法。 public List FilterCustomersByStatus(List source, string status) { return (List)sour
我在 Clojure 中使用 deftype 时遇到了问题。如果我运行以下代码: (defprotocol TestProt (geta [this]) (getb [this])) (def
给定以下类: public class MyType { public static implicit operator MyType(Func wrapper) { retu
我定义了一个简单的代数(具体)数据类型,MyType: data MyTpe = MyBool Bool | MyInt Int ...我正在尝试找到一种方法将任意函数(a->b)“转换”为关联的(M
我有一个在运行时动态创建新类型的应用程序,创建该类型的对象并将它们插入 object 类型的 MongoDB 数据库集合中。使用 shell 我可以看到对象被正确插入并且 _t 值是动态创建的类的正确
与仅使用 List(Of MyType) 相比,使用 ConcurrentBag(Of MyType) 有什么优势? The MSDN page on the CB指出 ConcurrentBag(O
我想通过使用map一对一地从异步函数中加载多个描述: Future> loadDescriptions(List questions) async { Iterable> iterable
我想在线程之间传递一些信息。原子听起来像是要使用的东西。我看了一下this 。并发现一个简单的结构,例如 struct MyType{ int val_a,val_b; float vals_
我得到的具体异常是: Unable to cast object of type NbtByte to type INbtTag 在这一行: tag = (INbtTag)new NbtByte(st
是的,我已经完成了标题相似的问题。它们似乎都不符合我所处的情况。这只是程序员向 View 发送了错误的对象类型。 这是我收到的确切错误消息: The model item passed into th
这是一个玩具示例: #[derive(Debug)] struct Int { v: i32, } #[derive(Debug)] struct Double { v: f64, }
在我没有编写但必须使用的代码中,使用 OpenCV(但它可以是任何东西)我遇到了类似的东西: void foo (long addrImage){ [...] Mat& image = *(M
我有一个自定义列表 MyList,它是 List 的扩展,并且我有一个我想执行的 IEnumerable(或 IQueryable).ToList( ) 上,但我猜,.ToMyList()。 如何实现
[Test] public void testMultiplication() { var five=new Dollar(5); Assert.AreEqual(new Dollar
假设我有一个类 MyType: sealed class MyType { static Type typeReference = typeof(MyType); //... } 给定
我有一个如下所示的 ArrayList: final List myList = new ArrayList<>(); MyType 看起来像这样: public class MyType {
我正在使用来自不同模块的类型,我们将其称为 OtherModule.MyType, 这段代码: var a = [OtherModule.MyType]() 将产生错误无效使用“()”来调用非函数类型
我在下面列出了一个相当人为的例子,来 self 正在研究的更大的东西。我遇到了我认为是关于使用 Any 类型的 Swift 编译器错误。 struct Labelable { let t: T
我正在使用 Dictionary在一个类(class)。该类实现了一个需要 IList 的接口(interface)被退回。有没有一种简单的方法可以将一个转换为另一个(无需复制整个内容)? 我目前的解
我是一名优秀的程序员,十分优秀!