我想在Haskell中创建一个函数,它根据给定的数据类型执行不同的操作。我认为课程应该做我想要的,但现在我遇到了问题。我希望能够做的是类似于:
let x1 = myFunction :: MyInstance1
let x2 = myFunction :: MyInstance2
并且它根据给定的实例执行不同的操作。
我目前的方法是
class MyClass a where
create :: Int -> a
doSomething :: a -> [Int]
myFunction :: [Int]
myFunction = doSomething $ create 4
instance MyClass MyInstance1 where
-- implementation of create and doSomething
instance MyClass MyInstance2 where
-- implementation of create and doSomething
然而,编译器告诉我"类型变量a0在模糊性检查中是不明确的,因为myFunction'"从我读过的内容来看,这与编译器不知道什么是“做什么”的实例有关。打电话。
那么有没有办法打电话给'做某事'在"泛型"方式并在以后强制执行数据类型?或者我的问题需要完全不同的方法吗?
---编辑---
所以我应用了 chi 对我的问题的答案,但它还没有完全解决它。这是我的代码
{-# LANGUAGE AllowAmbiguousTypes #-}
class C a where
myFunction :: Int
create :: Int -> a
doSomething :: a -> Int
-- anotherFunction :: Int -> Int
-- anotherFunction x = doSomething $ create 4
instance C Int where
myFunction = 1
create x = 2 * x
doSomething x = x + 4
instance C Bool where
myFunction = 2
create x = True
doSomething x = if x then 42 else 24
这会在提示符中编译和我
create @ Bool 4
create @ Int 4
返回预期结果。但是, anotherFunction 无法正确编译,并提供错误消息
Test.hs:8:23: error:
• Could not deduce (C a0) arising from a use of ‘doSomething’
from the context: C a
bound by the class declaration for ‘C’ at Test.hs:(3,1)-(8,44)
The type variable ‘a0’ is ambiguous
These potential instances exist:
instance C Bool -- Defined at Test.hs:15:10
instance C Int -- Defined at Test.hs:10:10
• In the expression: doSomething $ create 4
In an equation for ‘anotherFunction’:
anotherFunction x = doSomething $ create 4
Failed, modules loaded: none.
在此上下文中是否根本无法使用 doSomething ?我的想法是以相同的方式为所有实例实现该函数,然后编写
anotherFunction @ Bool 4
anotherFunction @ Int 6
答案 0 :(得分:4)
你需要几个扩展来做到这一点,但它是可行的。这是一个GHCi会议,显示:
> :set -XAllowAmbiguousTypes
> class C a where myFunction :: Int
> instance C Int where myFunction = 1
> instance C Bool where myFunction = 2
> :set -XTypeApplications
> myFunction @ Int
1
> myFunction @ Bool
2
“旧”解决方案是添加代理参数
class C a where myFunction :: proxy a -> Int
但希望这会在几年内淡出风格 - 我发现传递类型明显比传递代理更清晰。
完整代码,另一个例子:
{-# LANGUAGE AllowAmbiguousTypes, TypeApplications, ScopedTypeVariables #-}
class C a where
myFunction :: Int
create :: Int -> a
doSomething :: a -> Int
anotherFunction :: Int -> Int
anotherFunction x = doSomething $ create @ a 4
instance C Int where
myFunction = 1
create x = 2 * x
doSomething x = x + 4
instance C Bool where
myFunction = 2
create x = True
doSomething x = if x then 42 else 24
试验:
> :set -XTypeApplications
> anotherFunction @ Bool 4
42
> anotherFunction @ Int 6
12