可以结果`fun ::(SomeTypeClass a)=>也许是 - >如果我传递“Nothing”的不同类型值,结果会改变吗?

时间:2018-02-01 08:27:18

标签: haskell

几乎是标题,但让我们详细说明:

假设我有一些类型类SomeTypeClass和不同类型ABC,每个类型都有一个实例。

让我们进一步假设我有一个功能

fun :: (SomeTypeClass a) => Maybe a -> Result

对于某些类型常量Result

表达式

  1. fun (Nothing :: Maybe A)
  2. fun (Nothing :: Maybe B)
  3. fun (Nothing :: Maybe C)
  4. 以某种方式产生不同的结果?

    (可能是某些编译器扩展为fun提供了不同的实现,具体取决于参数类型等。)

5 个答案:

答案 0 :(得分:5)

当然,Result = StringSomeTypeClass a = (Monoid a, Show a)

import Data.Foldable
doSomething :: (Show a, Monoid a) => Maybe a -> String
doSomething = show . fold

doSomething (Nothing :: Maybe String) == "\"\""
doSomething (Nothing :: Maybe [Int] == "[]"
doSomething (Nothing :: Maybe (Product Int)) == "Product {getProduct=1}"
doSomething (Nothing :: Maybe (Sum Int)) == "Sum {getSum=0}"

当然不是唯一的例子,但可能是最简单的(也就是说,至少类似于你在实际代码中可能会遇到的东西)。

答案 1 :(得分:2)

我能想出来实现这一目标的最简单方法是以下黑客攻击:

{-# LANGUAGE ScopedTypeVariables #-}

data A = A
data B = B

class SomeClass a where
  doSomething :: a -> String

instance SomeClass A where
  doSomething _ = "always a"

instance SomeClass B where
  doSomething _ = "always b"

instance SomeClass a => SomeClass (Maybe a) where
  doSomething (Just x) = doSomething x
  doSomething Nothing = doSomething (undefined :: a)

main = print (doSomething (Nothing :: Maybe A), doSomething (Nothing :: Maybe B), doSomething (Just A))

您可以使用undefined数据类型绕过丑陋的data Proxy a = Proxy。我不确定这在实践中有多大用处,因为您无法检查AB的实例中的输入。

编辑:这是代理版本,您可以在Just a处检查输入:

{-# LANGUAGE FlexibleContexts, FlexibleInstances, UndecidableInstances, ScopedTypeVariables #-}

data A = A Int
data B = B Int

data Proxy a = Proxy

class SomeClass a where
  doSomething :: a -> String

instance SomeClass A where
  doSomething (A x) = "always A with " ++ show x

instance SomeClass B where
  doSomething (B x) = "always B with " ++ show x

instance SomeClass (Proxy A) where
    doSomething Proxy = "proxy A(Nothing)"

instance SomeClass (Proxy B) where
    doSomething Proxy = "proxy B(Nothing)"

instance (SomeClass a, SomeClass (Proxy a)) => SomeClass (Maybe a) where
  doSomething (Just x) = doSomething x
  doSomething Nothing = doSomething (Proxy :: Proxy a)

main = print (doSomething (Nothing :: Maybe A), doSomething (Nothing :: Maybe B), doSomething (Just $ A 2))

虽然感觉更像是黑客(UndecidableInstances yikes)

答案 2 :(得分:1)

作为参考最基本的例子,我发现:

module TestNothings where

class SomeClass a where
    doSomething :: Maybe a -> Int

newtype A = A Int deriving (Eq, Show)
newtype B = B Int deriving (Eq, Show)
newtype C = C Int deriving (Eq, Show)

instance SomeClass A where
    doSomething (Just (A i)) = i
    doSomething Nothing = 0

instance SomeClass B where
    doSomething (Just (B i)) = i
    doSomething Nothing = 1

instance SomeClass C where
    doSomething (Just (C i)) = i
    doSomething Nothing = 2

答案 3 :(得分:0)

添加另一个类型类助手可以避免{@ 1}}扩展可以避免如果我们引入另一个类型类助手,其默认ScopedTypeVariables实现调用ad-hoc“overloaded”fun使用的情况他们只对类型推断的论证:

Nothing

添加新类型后,可以使用新的type Result = String data A = A data B = B class SomeClass a where foo :: a -> Result instance SomeClass A where foo _ = "A" instance SomeClass B where foo _ = "B" class SomeClass a => Fun a where fun :: Maybe a -> Result fun (Just a) = foo a fun a = funNothing a funNothing :: Maybe a -> Result instance Fun A where funNothing _ = "No A" instance Fun B where funNothing _ = "No B" main = do putStrLn $ fun (Just A) putStrLn $ fun (Just B) putStrLn $ fun (Nothing :: Maybe A) putStrLn $ fun (Nothing :: Maybe B) 实例轻松扩展乐趣。

答案 4 :(得分:0)

我可能错了,但我从以下方面理解:

要实现这样的函数fun,您需要ad-hoc多态,即对于不同的输入类型,您需要a的不同实现。无法从Nothing中获得SomeTypeClass f :: Maybe a -> Result 的正确类型(即稀薄的空气),答案将是

但是,如果您的类型类fun具有以下功能:

f

然后fun = f 可以与f相同:

cd wordpress
sudo find . -type d -exec chmod 0755 {} \;
sudo find . -type f -exec chmod 0644 {} \;

现在,您可以通过在实例中实现define( 'FS_METHOD', 'direct' ); 的不同版本来实现ad-hoc多态性。即答案是,但您必须在类型类中实现问题的相关部分。